🐛 navmesh 无法正确寻路问题处理,增加测试用例 navmesh_example_test.go
This commit is contained in:
parent
07246aee7b
commit
f3998420bb
4
go.mod
4
go.mod
|
@ -11,6 +11,7 @@ require (
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
||||||
github.com/nats-io/nats.go v1.25.0
|
github.com/nats-io/nats.go v1.25.0
|
||||||
github.com/panjf2000/gnet v1.6.6
|
github.com/panjf2000/gnet v1.6.6
|
||||||
|
github.com/smartystreets/goconvey v1.8.0
|
||||||
github.com/sony/sonyflake v1.1.0
|
github.com/sony/sonyflake v1.1.0
|
||||||
github.com/tealeg/xlsx v1.0.5
|
github.com/tealeg/xlsx v1.0.5
|
||||||
github.com/tidwall/gjson v1.14.4
|
github.com/tidwall/gjson v1.14.4
|
||||||
|
@ -46,7 +47,6 @@ require (
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/smartystreets/assertions v1.13.1 // indirect
|
github.com/smartystreets/assertions v1.13.1 // indirect
|
||||||
github.com/smartystreets/goconvey v1.8.0 // indirect
|
|
||||||
github.com/templexxx/cpu v0.0.9 // indirect
|
github.com/templexxx/cpu v0.0.9 // indirect
|
||||||
github.com/templexxx/xorsimd v0.4.1 // indirect
|
github.com/templexxx/xorsimd v0.4.1 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
|
@ -59,11 +59,9 @@ require (
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/crypto v0.9.0 // indirect
|
golang.org/x/crypto v0.9.0 // indirect
|
||||||
golang.org/x/mod v0.9.0 // indirect
|
|
||||||
golang.org/x/net v0.10.0 // indirect
|
golang.org/x/net v0.10.0 // indirect
|
||||||
golang.org/x/sys v0.8.0 // indirect
|
golang.org/x/sys v0.8.0 // indirect
|
||||||
golang.org/x/text v0.9.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
golang.org/x/tools v0.7.0 // indirect
|
|
||||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||||
|
|
7
go.sum
7
go.sum
|
@ -24,8 +24,6 @@ github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
|
|
||||||
github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
|
|
||||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
@ -72,7 +70,6 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU=
|
github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU=
|
||||||
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
|
||||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||||
|
@ -210,8 +207,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
|
||||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -264,8 +259,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||||
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
|
||||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
|
@ -71,7 +71,7 @@ func GetDirectionNextWithCoordinateArray[V generic.SignedNumber](direction Direc
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDirectionNextWithPos 获取位置在特定宽度和特定方向上的下一个位置
|
// GetDirectionNextWithPos 获取位置在特定宽度和特定方向上的下一个位置
|
||||||
// - 需要注意的是,在左右方向时,当下一个位置不在游戏区域内时,将会返回上一行的末位置或下一行的首位置
|
// - 需要注意的是,在左右方向时,当下一个位置不在矩形区域内时,将会返回上一行的末位置或下一行的首位置
|
||||||
func GetDirectionNextWithPos[V generic.SignedNumber](direction Direction, width, pos V) V {
|
func GetDirectionNextWithPos[V generic.SignedNumber](direction Direction, width, pos V) V {
|
||||||
switch direction {
|
switch direction {
|
||||||
case DirectionUp:
|
case DirectionUp:
|
||||||
|
|
|
@ -14,9 +14,29 @@ func NewLine[V generic.SignedNumber](start, end Point[V]) Line[V] {
|
||||||
return Line[V]{start, end}
|
return Line[V]{start, end}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewLineCap 创建一根包含数据的线段
|
||||||
|
func NewLineCap[V generic.SignedNumber, Data any](start, end Point[V], data Data) LineCap[V, Data] {
|
||||||
|
return LineCap[V, Data]{NewLine(start, end), data}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewLineCapWithLine 通过已有线段创建一根包含数据的线段
|
||||||
|
func NewLineCapWithLine[V generic.SignedNumber, Data any](line Line[V], data Data) LineCap[V, Data] {
|
||||||
|
return LineCap[V, Data]{line, data}
|
||||||
|
}
|
||||||
|
|
||||||
// Line 通过两个点表示一根线段
|
// Line 通过两个点表示一根线段
|
||||||
type Line[V generic.SignedNumber] [2]Point[V]
|
type Line[V generic.SignedNumber] [2]Point[V]
|
||||||
|
|
||||||
|
// LineCap 可以包含一份额外数据的线段
|
||||||
|
type LineCap[V generic.SignedNumber, Data any] struct {
|
||||||
|
Line[V]
|
||||||
|
Data Data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *LineCap[V, Data]) GetData() Data {
|
||||||
|
return slf.Data
|
||||||
|
}
|
||||||
|
|
||||||
// GetPoints 获取该线段的两个点
|
// GetPoints 获取该线段的两个点
|
||||||
func (slf Line[V]) GetPoints() [2]Point[V] {
|
func (slf Line[V]) GetPoints() [2]Point[V] {
|
||||||
return slf
|
return slf
|
||||||
|
@ -92,11 +112,13 @@ func CalcLineIsCollinear[V generic.SignedNumber](line1, line2 Line[V], tolerance
|
||||||
|
|
||||||
// CalcLineIsOverlap 通过对点进行排序来检查两条共线线段是否重叠,返回重叠线段
|
// CalcLineIsOverlap 通过对点进行排序来检查两条共线线段是否重叠,返回重叠线段
|
||||||
func CalcLineIsOverlap[V generic.SignedNumber](line1, line2 Line[V]) (line Line[V], overlap bool) {
|
func CalcLineIsOverlap[V generic.SignedNumber](line1, line2 Line[V]) (line Line[V], overlap bool) {
|
||||||
var shapes = []Shape[V]{
|
l1ps, l1pe := NewPointCapWithPoint(line1.GetStart(), true), NewPointCapWithPoint(line1.GetEnd(), true)
|
||||||
{line1.GetStart(), line1.GetEnd(), line1.GetStart()},
|
l2ps, l2pe := NewPointCapWithPoint(line2.GetStart(), false), NewPointCapWithPoint(line2.GetEnd(), false)
|
||||||
{line1.GetStart(), line1.GetEnd(), line1.GetEnd()},
|
var shapes = [][]PointCap[V, bool]{
|
||||||
{line2.GetStart(), line2.GetEnd(), line2.GetStart()},
|
{l1ps, l1pe, l1ps},
|
||||||
{line2.GetStart(), line2.GetEnd(), line2.GetEnd()},
|
{l1ps, l1pe, l1pe},
|
||||||
|
{l2ps, l2pe, l2ps},
|
||||||
|
{l2ps, l2pe, l2pe},
|
||||||
}
|
}
|
||||||
sort.Slice(shapes, func(i, j int) bool {
|
sort.Slice(shapes, func(i, j int) bool {
|
||||||
a, b := shapes[i], shapes[j]
|
a, b := shapes[i], shapes[j]
|
||||||
|
@ -109,10 +131,10 @@ func CalcLineIsOverlap[V generic.SignedNumber](line1, line2 Line[V]) (line Line[
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
notOverlap := shapes[0][0].Equal(shapes[1][0]) && shapes[0][1].Equal(shapes[1][1])
|
notOverlap := shapes[1][0].GetData() == shapes[2][0].GetData()
|
||||||
singlePointOverlap := shapes[1][2].Equal(shapes[2][2])
|
singlePointOverlap := shapes[1][2].Equal(shapes[2][2].Point)
|
||||||
if notOverlap || singlePointOverlap {
|
if notOverlap || singlePointOverlap {
|
||||||
return line, false
|
return line, false
|
||||||
}
|
}
|
||||||
return NewLine(shapes[1][2], shapes[2][2]), true
|
return NewLine(shapes[1][2].Point, shapes[2][2].Point), true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package navmesh
|
package navmesh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kercylan98/minotaur/utils/astar"
|
|
||||||
"github.com/kercylan98/minotaur/utils/generic"
|
"github.com/kercylan98/minotaur/utils/generic"
|
||||||
"github.com/kercylan98/minotaur/utils/geometry"
|
"github.com/kercylan98/minotaur/utils/geometry"
|
||||||
|
"github.com/kercylan98/minotaur/utils/geometry/astar"
|
||||||
"github.com/kercylan98/minotaur/utils/maths"
|
"github.com/kercylan98/minotaur/utils/maths"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -178,6 +178,9 @@ func (slf *NavMesh[V]) FindPath(start, end geometry.Point[V]) (result []geometry
|
||||||
for i := 0; i < len(path)-1; i++ {
|
for i := 0; i < len(path)-1; i++ {
|
||||||
current := path[i]
|
current := path[i]
|
||||||
next := path[i+1]
|
next := path[i+1]
|
||||||
|
if current.id == next.id {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var portal geometry.Line[V]
|
var portal geometry.Line[V]
|
||||||
var find bool
|
var find bool
|
||||||
|
@ -208,8 +211,7 @@ func (slf *NavMesh[V]) FindPath(start, end geometry.Point[V]) (result []geometry
|
||||||
}
|
}
|
||||||
|
|
||||||
func (slf *NavMesh[V]) generateLink() {
|
func (slf *NavMesh[V]) generateLink() {
|
||||||
refer := len(slf.meshShapes)
|
for i := 0; i < len(slf.meshShapes); i++ {
|
||||||
for i := 0; i < refer; i++ {
|
|
||||||
shapePkg := slf.meshShapes[i]
|
shapePkg := slf.meshShapes[i]
|
||||||
shapeCentroid := shapePkg.Centroid()
|
shapeCentroid := shapePkg.Centroid()
|
||||||
shapeBoundingRadius := shapePkg.BoundingRadius()
|
shapeBoundingRadius := shapePkg.BoundingRadius()
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
package navmesh_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/kercylan98/minotaur/utils/geometry"
|
||||||
|
"github.com/kercylan98/minotaur/utils/geometry/navmesh"
|
||||||
|
"github.com/kercylan98/minotaur/utils/maths"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleNavMesh_FindPath() {
|
||||||
|
fp := geometry.FloorPlan{
|
||||||
|
"=================================",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"X X",
|
||||||
|
"=================================",
|
||||||
|
}
|
||||||
|
|
||||||
|
var walkable []geometry.Shape[int]
|
||||||
|
walkable = append(walkable,
|
||||||
|
geometry.NewShape(
|
||||||
|
geometry.NewPoint(5, 5),
|
||||||
|
geometry.NewPoint(15, 5),
|
||||||
|
geometry.NewPoint(15, 15),
|
||||||
|
geometry.NewPoint(5, 15),
|
||||||
|
),
|
||||||
|
geometry.NewShape(
|
||||||
|
geometry.NewPoint(15, 5),
|
||||||
|
geometry.NewPoint(25, 5),
|
||||||
|
geometry.NewPoint(25, 15),
|
||||||
|
geometry.NewPoint(15, 15),
|
||||||
|
),
|
||||||
|
geometry.NewShape(
|
||||||
|
geometry.NewPoint(15, 15),
|
||||||
|
geometry.NewPoint(25, 15),
|
||||||
|
geometry.NewPoint(25, 25),
|
||||||
|
geometry.NewPoint(15, 25),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, shape := range walkable {
|
||||||
|
for _, edge := range shape.Edges() {
|
||||||
|
sx, bx := maths.MinMax(edge.GetStart().GetX(), edge.GetEnd().GetX())
|
||||||
|
sy, by := maths.MinMax(edge.GetStart().GetY(), edge.GetEnd().GetY())
|
||||||
|
|
||||||
|
for x := sx; x <= bx; x++ {
|
||||||
|
for y := sy; y <= by; y++ {
|
||||||
|
fp.Put(geometry.NewPoint[int](int(x), int(y)), '+')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nm := navmesh.NewNavMesh(walkable, 0)
|
||||||
|
path := nm.FindPath(
|
||||||
|
geometry.NewPoint(6, 6),
|
||||||
|
geometry.NewPoint(18, 24),
|
||||||
|
)
|
||||||
|
for _, point := range path {
|
||||||
|
fp.Put(geometry.NewPoint(point.GetX(), point.GetY()), 'G')
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(fp)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// =================================
|
||||||
|
// X X
|
||||||
|
// X X
|
||||||
|
// X X
|
||||||
|
// X X
|
||||||
|
// X +++++++++++++++++++++ X
|
||||||
|
// X +G + + X
|
||||||
|
// X + + + X
|
||||||
|
// X + + + X
|
||||||
|
// X + + + X
|
||||||
|
// X + + + X
|
||||||
|
// X + + + X
|
||||||
|
// X + + + X
|
||||||
|
// X + + + X
|
||||||
|
// X + + + X
|
||||||
|
// X ++++++++++G++++++++++ X
|
||||||
|
// X + + X
|
||||||
|
// X + + X
|
||||||
|
// X + + X
|
||||||
|
// X + + X
|
||||||
|
// X + + X
|
||||||
|
// X + + X
|
||||||
|
// X + + X
|
||||||
|
// X + + X
|
||||||
|
// X + G + X
|
||||||
|
// X +++++++++++ X
|
||||||
|
// X X
|
||||||
|
// X X
|
||||||
|
// =================================
|
||||||
|
}
|
|
@ -74,6 +74,14 @@ func NewPointCapWithData[V generic.SignedNumber, D any](x, y V, data D) PointCap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPointCapWithPoint 通过设置数据的方式创建一个由已有坐标组成的点,这个点具有一个数据容量
|
||||||
|
func NewPointCapWithPoint[V generic.SignedNumber, D any](point Point[V], data D) PointCap[V, D] {
|
||||||
|
return PointCap[V, D]{
|
||||||
|
Point: point,
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// PointCap 表示了一个由 x、y 坐标组成的点,这个点具有一个数据容量
|
// PointCap 表示了一个由 x、y 坐标组成的点,这个点具有一个数据容量
|
||||||
type PointCap[V generic.SignedNumber, D any] struct {
|
type PointCap[V generic.SignedNumber, D any] struct {
|
||||||
Point[V]
|
Point[V]
|
||||||
|
|
|
@ -328,7 +328,10 @@ func GetRectangleFullPos[V generic.SignedNumber](width, height V) (result []V) {
|
||||||
func CalcRectangleCentroid[V generic.SignedNumber](shape Shape[V]) Point[V] {
|
func CalcRectangleCentroid[V generic.SignedNumber](shape Shape[V]) Point[V] {
|
||||||
x, y := V(0), V(0)
|
x, y := V(0), V(0)
|
||||||
length := V(shape.PointCount())
|
length := V(shape.PointCount())
|
||||||
|
for _, point := range shape.Points() {
|
||||||
|
x += point.GetX()
|
||||||
|
y += point.GetY()
|
||||||
|
}
|
||||||
x /= length
|
x /= length
|
||||||
y /= length
|
y /= length
|
||||||
return NewPoint(x, y)
|
return NewPoint(x, y)
|
||||||
|
|
|
@ -71,7 +71,7 @@ func (slf Shape[V]) PointCount() int {
|
||||||
func (slf Shape[V]) Contains(point Point[V]) bool {
|
func (slf Shape[V]) Contains(point Point[V]) bool {
|
||||||
x, y := point.GetXY()
|
x, y := point.GetXY()
|
||||||
inside := false
|
inside := false
|
||||||
for i, j := -1, len(slf)-1; i < len(slf); j, i = i, i+1 {
|
for i, j := 0, len(slf)-1; i < len(slf); i, j = i+1, i {
|
||||||
ix := slf[i].GetX()
|
ix := slf[i].GetX()
|
||||||
iy := slf[i].GetY()
|
iy := slf[i].GetY()
|
||||||
jx := slf[j].GetX()
|
jx := slf[j].GetX()
|
||||||
|
|
Loading…
Reference in New Issue