Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Imports System.Drawing
- Public Class Pathfinder
- Dim Nodes As List(Of Node)
- Public PathList As List(Of Node)
- Public OpenList As List(Of Node)
- Public CloseList As List(Of Node)
- Dim Start As Point
- Dim Goal As Point
- Public UseCutCorners As Boolean
- Public UseManhattan As Boolean
- Public UseDiagonal As Boolean
- Public Sub New(Nodes As List(Of Node))
- Me.Nodes = Nodes
- Me.OpenList = New List(Of Node)
- Me.CloseList = New List(Of Node)
- Me.PathList = New List(Of Node)
- Me.UseCutCorners = False
- Me.UseManhattan = True
- Me.UseDiagonal = True
- End Sub
- Public Sub ClearResults()
- Me.OpenList.Clear()
- Me.CloseList.Clear()
- Me.PathList.Clear()
- End Sub
- Public Sub FindPath(start As Point, goal As Point)
- Me.Start = start
- Me.Goal = goal
- ClearResults()
- Dim HCost As Double = GetHeuristic(start, goal, UseManhattan)
- Dim current As New Node(start, Nothing, 0, HCost, 0)
- OpenList.Add(current)
- While OpenList.Count > 0
- OpenList = OpenList.OrderBy(Function(n) n.FCost).ToList()
- current = OpenList(0)
- If current.Tile = goal Then
- While current.Parent IsNot Nothing ' the ONLY null parent is the start node
- PathList.Add(current)
- current = current.Parent
- End While
- Return
- End If
- OpenList.Remove(current)
- CloseList.Add(current)
- For x As Integer = -1 To 1
- For y As Integer = -1 To 1
- Dim xi As Integer = current.Tile.X + x
- Dim yi As Integer = current.Tile.Y + y
- 'No Diagonal
- If GetUseDiagonal(x, y, UseDiagonal) Then
- Continue For
- End If
- Dim at As Node = GetNode(xi, yi)
- If at Is Nothing Then
- Continue For
- End If
- If at.Weight > 0 Then
- Continue For
- End If
- Dim a As New Point(xi, yi)
- 'at.Parent = current
- If GetCutCorner(x, y, current, Me.UseCutCorners) Then
- Continue For
- End If
- Dim g_cost As Double = current.GCost + GetDistance(current.Tile, a) 'use 10 or 14 instead of getdistance here
- Dim h_cost As Double = GetHeuristic(a, goal, UseManhattan)
- Dim newNode As New Node(a, current, g_cost, h_cost, at.Weight)
- If OnCloseList(newNode) And g_cost >= newNode.GCost Then
- Continue For
- End If
- If Not OnOpenList(newNode) Or g_cost < newNode.GCost Then
- OpenList.Add(newNode)
- End If
- Next
- Next
- End While
- End Sub
- Public Function OnOpenList(ByVal checking As Node) As Boolean
- Return OpenList.Find(Function(n) n.Tile = checking.Tile) IsNot Nothing
- End Function
- Public Function OnCloseList(ByVal checking As Node) As Boolean
- Return CloseList.Find(Function(n) n.Tile = checking.Tile) IsNot Nothing
- End Function
- Public Function OnPathList(ByVal checking As Node) As Boolean
- Return PathList.Find(Function(n) n.Tile = checking.Tile) IsNot Nothing
- End Function
- Private Function GetUseDiagonal(ByVal x As Integer, ByVal y As Integer, ByVal useDiagonal As Boolean) As Boolean
- 'No Diagonal
- If Not useDiagonal And ((x = -1 And y = -1) Or (x = 1 And y = 1) Or (x = -1 And y = 1) Or (x = 1 And y = -1)) Then
- Return True
- End If
- Return False
- End Function
- Private Function GetCutCorner(ByVal x As Integer, ByVal y As Integer, checking As Node, ByVal useCutCorners As Boolean) As Boolean
- If Not useCutCorners Then
- 'No corner cutting
- If x = 1 And y = 1 Then 'checking down right
- Dim rightNode As Node = GetNode(checking.Tile.X + 1, checking.Tile.Y) 'parent right
- If rightNode IsNot Nothing Then
- If rightNode.Weight > 0 Then
- Return True
- End If
- End If
- Dim bottomNode As Node = GetNode(checking.Tile.X, checking.Tile.Y + 1) 'parent down
- If bottomNode IsNot Nothing Then
- If bottomNode.Weight > 0 Then
- Return True
- End If
- End If
- End If
- If x = 1 And y = -1 Then 'checking up right
- Dim rightNode As Node = GetNode(checking.Tile.X + 1, checking.Tile.Y) 'parent right
- If rightNode IsNot Nothing Then
- If rightNode.Weight > 0 Then
- Return True
- End If
- End If
- Dim upNode As Node = GetNode(checking.Tile.X, checking.Tile.Y - 1) 'parent up
- If upNode IsNot Nothing Then
- If upNode.Weight > 0 Then
- Return True
- End If
- End If
- End If
- If x = -1 And y = 1 Then 'checking down left
- Dim leftNode As Node = GetNode(checking.Tile.X - 1, checking.Tile.Y)
- If leftNode IsNot Nothing Then
- If leftNode.Weight > 0 Then
- Return True
- End If
- End If
- Dim bottomNode As Node = GetNode(checking.Tile.X, checking.Tile.Y + 1) 'parent down
- If bottomNode IsNot Nothing Then
- If bottomNode.Weight > 0 Then
- Return True
- End If
- End If
- End If
- If x = -1 And y = -1 Then 'checking up left
- Dim leftNode As Node = GetNode(checking.Tile.X - 1, checking.Tile.Y)
- If leftNode IsNot Nothing Then
- If leftNode.Weight > 0 Then
- Return True
- End If
- End If
- Dim upNode As Node = GetNode(checking.Tile.X, checking.Tile.Y - 1) 'parent up
- If upNode IsNot Nothing Then
- If upNode.Weight > 0 Then
- Return True
- End If
- End If
- End If
- End If
- Return False
- End Function
- Private Function GetHeuristic(start As Point, goal As Point, ByVal useManhattan As Boolean) As Double
- If useManhattan Then
- Return GetManhatnan(start, goal)
- Else
- Return GetDistance(start, goal)
- End If
- End Function
- Private Function GetManhatnan(start As Point, goal As Point)
- Return Math.Abs(goal.X - start.X) + Math.Abs(goal.Y - start.Y)
- End Function
- Private Function GetDistance(start As Point, goal As Point) As Double
- Dim dx As Double = start.X - goal.X
- Dim dy As Double = start.Y - goal.Y
- Return Math.Sqrt(dx * dx + dy * dy)
- End Function
- Public Function GetNode(x As Integer, y As Integer) As Node
- Return Nodes.Find(Function(n) n.Tile.X = x And n.Tile.Y = y)
- End Function
- End Class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement