Results 1 to 10 of 10

Thread: Path-Finding

  1. #1

    Thread Starter
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051

    Path-Finding

    Hi all, here's the situation: (if you just want to get to my problem scroll down to the code listing)

    I'm making a 2d tile-based game. All is going well, i have inhabited it with various monsters, created lots of maps etc. I'm now trying to expand the possibilities by adding a general path finding function to get from A to B in my map.

    I have managed to use the A* algorythm in one type of my monsters fine. The only trouble is that on big maps it noticably slows down my game.

    What i thought i could do is pre-calculate the direction to move to get from A to B.

    This I have also managed to do, using the A* algorythm. However, as each calculation of a path is independent of the other this creates a huge pause when calculating all the paths (as the # of calculations required is GridWidth^2*gridheight^2).

    My thought was that i could adapt the A* algorythm so that i didn't need to do similar calculations more than once.

    Below is the algorythm i devised.

    Create a closed list and an open list, for storing nodes
    Code:
    Loop through each node that the destination can see, adding them onto the open list
    
    While the open list is not empty:
        Get a node from the open list, then remove it from that list
        If this node is in the closed list ignore it
        For each node that this node can see:
            If it's not on the open list then calculate it's distance from the destination via 'thisnode'
            If it is on the open list check it's distance, and if it's better to go via 'thisnode' then update the distance
    
    'At this point each node as its distance from the destination (i hope)
    
    For each possible position on the grid:
        Loop through each node that this position can see, finding the one with the shortest distance to the destination
        Once we have the best node (shortest distance), store the direction we need to move in to get from our position to that node and store it

    I hope you're still with me here. The implimentation i've put below doesn't work. I was just wondering if anyone could see anything wrong with the above algorythm, or my implimentation. FYI, everything is syntactically correct and the algorythm runs, it just doesn't work correctly.
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


  2. #2

    Thread Starter
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051
    The overall function
    VB Code:
    1. frmProgress.ProgressBar.Width = 0
    2. For i = 2 To GridWidth - 1
    3.     For j = 2 To GridHeight - 1
    4.         If Not ThinkGrid(i, j).Type = harddirto Then
    5.             NodeNetwork.ResetNodeData
    6.             GetMovePathsUsingNodes i, j
    7.             frmProgress.ProgressBar.Width = frmProgress.Width * (((i - 1) / (GridWidth - 2)) + ((j - 1) / (GridHeight - 2)) / (GridWidth - 2)) 'Update the progress bar
    8.             DoEvents
    9.         End If
    10.     Next j
    11. Next i
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


  3. #3

    Thread Starter
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051
    The function that given a destination, gets all directions for all possible source positions
    VB Code:
    1. Public Sub GetMovePathsUsingNodes(DestX As Integer, DestY As Integer)
    2.     Dim i As Integer
    3.     Dim j As Integer
    4.     Dim BestNode As TPathNode
    5.     Dim CurrentNode As New TNodeListElement
    6.     Dim TempNode As TPathNode
    7.     Dim NodesNRDest As New TNodeList
    8.     Dim NodesToCheck As New TNodeList
    9.     Dim CheckedNodes As New TNodeList
    10.     'This routine uses a method similar to that of the other one,
    11.     'except that it gets lots of paths from the same data (and so is faster)
    12.    
    13.     Set CurrentNode = NodeNetwork.Nodes.Start
    14.    
    15.     If IsVisible(DestX, DestY, CurrentNode.Data.X, CurrentNode.Data.Y) Then
    16.         Set TempNode = New TPathNode
    17.         TempNode.X = DestX
    18.         TempNode.Y = DestY
    19.         CurrentNode.Data.Distance = GetDistance(TempNode, CurrentNode.Data)
    20.         NodesNRDest.Add CurrentNode.Data
    21.         NodesToCheck.Add CurrentNode.Data
    22.     End If
    23.     Do
    24.         If Not Exists(CurrentNode.NextLE) Then Exit Do
    25.         Set CurrentNode = CurrentNode.NextLE
    26.        
    27.         If IsVisible(DestX, DestY, CurrentNode.Data.X, CurrentNode.Data.Y) Then
    28.             Set TempNode = New TPathNode
    29.             TempNode.X = DestX
    30.             TempNode.Y = DestY
    31.             CurrentNode.Data.Distance = GetDistance(TempNode, CurrentNode.Data)
    32.             NodesNRDest.Add CurrentNode.Data
    33.             NodesToCheck.Add CurrentNode.Data
    34.         End If
    35.     Loop Until Not Exists(CurrentNode.NextLE)
    36.    
    37.     'NodesNRDest now contains a list of all nodes that can see the destination as does NodesToCheck
    38.    
    39.         While Not NodesToCheck.IsEmpty
    40.         Set TempNode = NodesToCheck.GetTop
    41.         NodesToCheck.RemoveTop
    42.         CheckedNodes.Add TempNode
    43.        
    44.         'Check Up
    45.         If Exists(TempNode.UpLink) Then
    46.             If Not CheckedNodes.AlreadyExists(TempNode.UpLink) Then
    47.                 If NodesToCheck.AlreadyExists(TempNode.UpLink) And (TempNode.UpLink.Distance > 0 Or (TempNode.UpLink.X = DestX And TempNode.UpLink.Y = DestY)) Then
    48.                     If TempNode.Distance + GetDistance(TempNode, TempNode.UpLink) < TempNode.UpLink.Distance Then
    49.                         TempNode.UpLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.UpLink)
    50.                         'Possibly reorder the list
    51.                     End If
    52.                 Else
    53.                     NodesToCheck.Add TempNode.UpLink
    54.                     TempNode.UpLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.UpLink)
    55.                 End If
    56.             Else
    57.                 'If TempNode.Distance + GetDistance(TempNode, TempNode.UpLink) < TempNode.UpLink.Distance Then
    58.                 '    TempNode.UpLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.UpLink)
    59.                 '    'Possibly reorder the list
    60.                 'End If
    61.             End If
    62.         End If
    63.        
    64.         'Check Down
    65.         If Exists(TempNode.DownLink) Then
    66.             If Not CheckedNodes.AlreadyExists(TempNode.DownLink) Then
    67.                 If NodesToCheck.AlreadyExists(TempNode.DownLink) And (TempNode.DownLink.Distance > 0 Or (TempNode.DownLink.X = DestX And TempNode.DownLink.Y = DestY)) Then
    68.                     If TempNode.Distance + GetDistance(TempNode, TempNode.DownLink) < TempNode.DownLink.Distance Then
    69.                         TempNode.DownLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.DownLink)
    70.                         'Possibly reorder the list
    71.                     End If
    72.                 Else
    73.                     NodesToCheck.Add TempNode.DownLink
    74.                     TempNode.DownLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.DownLink)
    75.                 End If
    76.             Else
    77.                 'If TempNode.Distance + GetDistance(TempNode, TempNode.DownLink) < TempNode.DownLink.Distance Then
    78.                 '    TempNode.DownLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.DownLink)
    79.                 '    'Possibly reorder the list
    80.                 'End If
    81.             End If
    82.         End If
    83.        
    84.         'Check Left
    85.         If Exists(TempNode.LeftLink) Then
    86.             If Not CheckedNodes.AlreadyExists(TempNode.LeftLink) Then
    87.                 If NodesToCheck.AlreadyExists(TempNode.LeftLink) And (TempNode.LeftLink.Distance > 0 Or (TempNode.LeftLink.X = DestX And TempNode.LeftLink.Y = DestY)) Then
    88.                     If TempNode.Distance + GetDistance(TempNode, TempNode.LeftLink) < TempNode.LeftLink.Distance Then
    89.                         TempNode.LeftLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.LeftLink)
    90.                         'Possibly reorder the list
    91.                     End If
    92.                 Else
    93.                     NodesToCheck.Add TempNode.LeftLink
    94.                     TempNode.LeftLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.LeftLink)
    95.                 End If
    96.             Else
    97.                 'If TempNode.Distance + GetDistance(TempNode, TempNode.LeftLink) < TempNode.LeftLink.Distance Then
    98.                 '    TempNode.LeftLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.LeftLink)
    99.                 '    'Possibly reorder the list
    100.                 'End If
    101.             End If
    102.         End If
    103.        
    104.         'Check Right
    105.         If Exists(TempNode.RightLink) Then
    106.             If Not CheckedNodes.AlreadyExists(TempNode.RightLink) Then
    107.                 If NodesToCheck.AlreadyExists(TempNode.RightLink) And (TempNode.RightLink.Distance > 0 Or (TempNode.RightLink.X = DestX And TempNode.RightLink.Y = DestY)) Then
    108.                     If TempNode.Distance + GetDistance(TempNode, TempNode.RightLink) < TempNode.RightLink.Distance Then
    109.                         TempNode.RightLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.RightLink)
    110.                         'Possibly reorder the list
    111.                     End If
    112.                 Else
    113.                     NodesToCheck.Add TempNode.RightLink
    114.                     TempNode.RightLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.RightLink)
    115.                 End If
    116.             Else
    117.                 'If TempNode.Distance + GetDistance(TempNode, TempNode.RightLink) < TempNode.RightLink.Distance Then
    118.                 '    TempNode.RightLink.Distance = TempNode.Distance + GetDistance(TempNode, TempNode.RightLink)
    119.                 '    'Possibly reorder the list
    120.                 'End If
    121.             End If
    122.         End If
    123.     Wend
    124.    
    125.     'Now every node has its distance from the destination associated with it.
    126.    
    127.     'Loop through every possible place that could get to the destination
    128.     For i = 2 To GridWidth - 1
    129.         For j = 2 To GridHeight - 1
    130.             If ThinkGrid(i, j).Type = harddirto Or NodeNetwork.Nodes.IsEmpty Then
    131.                 RouteData(i, j, DestX, DestY).PathExists = False
    132.             Else
    133.                 If IsVisible(i, j, DestX, DestY) Then
    134.                     'There is a direct route between the monster and this node
    135.                     RouteData(i, j, DestX, DestY).Direction = GetDirection(i, j, DestX, DestY)
    136.                     RouteData(i, j, DestX, DestY).PathExists = True
    137.                 Else
    138.                     If Not (i = DestX And j = DestY) Then
    139.                         'The src isn't the dest, and the src is an open tile
    140.                         'Loop through each node that the monster can see, and find the one with the shortest distance to the player, and workout how to get to it (a direction)
    141.                         Set CurrentNode = CheckedNodes.Start
    142.                        
    143.                         If IsVisible(i, j, CurrentNode.Data.X, CurrentNode.Data.Y) And Not (i = CurrentNode.Data.X And j = CurrentNode.Data.Y) Then
    144.                             If Exists(BestNode) Then
    145.                                 Set TempNode = New TPathNode
    146.                                 TempNode.X = i
    147.                                 TempNode.Y = j
    148.                                 If BestNode.Distance + GetDistance(BestNode, TempNode) > CurrentNode.Data.Distance + GetDistance(CurrentNode.Data, TempNode) Then
    149.                                     Set BestNode = CurrentNode.Data
    150.                                 End If
    151.                             Else
    152.                                 Set BestNode = CurrentNode.Data
    153.                             End If
    154.                         End If
    155.                         Do
    156.                             If Not Exists(CurrentNode.NextLE) Then Exit Do
    157.                             Set CurrentNode = CurrentNode.NextLE
    158.                            
    159.                             If IsVisible(i, j, CurrentNode.Data.X, CurrentNode.Data.Y) And Not (i = CurrentNode.Data.X And j = CurrentNode.Data.Y) Then
    160.                                 If Exists(BestNode) Then
    161.                                     If BestNode.Distance + GetDistance(BestNode, TempNode) > CurrentNode.Data.Distance + GetDistance(CurrentNode.Data, TempNode) Then
    162.                                         Set BestNode = CurrentNode.Data
    163.                                     End If
    164.                                 Else
    165.                                     Set BestNode = CurrentNode.Data
    166.                                 End If
    167.                             End If
    168.                         Loop Until Not Exists(CurrentNode.NextLE)
    169.                        
    170.                         If Exists(BestNode) Then
    171.                             RouteData(i, j, DestX, DestY).PathExists = True
    172.                             RouteData(i, j, DestX, DestY).Direction = GetDirection(i, j, BestNode.X, BestNode.Y)
    173.                             Set BestNode = Nothing
    174.                         End If
    175.                     End If
    176.                 End If
    177.             End If
    178.         Next j
    179.     Next i
    180. End Sub
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


  4. #4
    New Member
    Join Date
    Apr 2003
    Posts
    15
    I have no clue what the A* is but here is what you should do. Dijkstra's Algo. Here is why. You have a modern computer with tons of disk space. You could create a data map of the PERFECT optimal route from every space on your map to every other space on your map. You do all this processing before your game runs and store the data as a text file. It'll be big; maybe 10 to 100mb depending on the size of your maps. Then you read this data into a multi demensional array and every time a monster needs to move you pass the monsters current XY and the target XY into a function you wrote and it returns the next XY for your critter. The time involved is a simple array lookup.

    This will work because everytime you run DA for a specific target node it weighs every posible nodes proximitly to the target node based on the PERFECT optimal routes. So pick any other node on the map and that node has only one node that represents the optimal path to the target. You store one array for each target node. The 2D array uses the maps X,Y to corespond to another X,Y. TheTargetArray(MonsterX, MonsterY) = Next MonsterX,Y

    This is some work up front and alot of storage space but you will not find a faster or more acurate pathfinding solution.

    Feel free to contact me for more details.

  5. #5
    Lively Member
    Join Date
    May 2000
    Posts
    84
    I have a few questions about the data set, not the method you are using, that might lead to a possible solution.

    1. What dimensions are these maps? 100x100? 1000X1000?

    2. When the map is created do walls or otherwise impassible
    areas use one full tile or do they border the edges of the
    tiles?

    3. Are the nodes you referred to in the first post adjacent tiles
    another or are they only at points such as intersections.

    All of these questions lead to one main idea.
    * Is it possible to reduce your data set ? *

    I have used dijkstra's implementation with VB in my own path fining program and it works fast on maps that are 20x20 tiles in size. I preprocess the maps and create a Decision Node Map.

    These nodes are important because they dont bother with all of the possibilities of going to adjacent tiles. For example a node is placed at corridor intersections but NOT at any point in an open area (after all in an open area there are thousands of paths between two points) In open areas I only have nodes at the corners, at corridor entrances to the area, and at the destination within the open area. If I ever have to cross the open area then all I did was calculate the tile path of a straight line.

    As a last resort you may want to think about writing a c++ DLL file that will perform the algorithm. Feed it an adjacency matrix and return an array of consecutive nodes.

  6. #6

    Thread Starter
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051
    Thanks for your replys.

    Re Mark:

    I have heard of Dykstra's algorythm and did concider using it. However, the trouble with this algorythm, (and the A*) is that it has no memory of previous searches. I know you pre-proces the map to make a graph, but the actual tracing of the graph is the bit that takes the time.

    I have already done exactly what you've described using the A* algorythm, and so i think i'll stick to adapting it, as i already have a full understanding of it.

    FYI the A* algorythm also projuces the best path, and is recognised by most academics as the fastest (according to numerus sources).


    Re Illuminator:

    1: Absolute max dimensions are 100x100

    So the saved file size is about tops 15MB

    2: The wals are 1 tile each.

    3:Nodes are not at all tiles, just ones of note, i.e. entrances to areas, exits to areas, corners of passageways etc. All nodes can 'see' eachother in a straight line.


    I have thought of most of the obvious optimization methods (such as using nodes, not every open tile in the algorythm). I have already completed a working algorythm as you both describe. I don't have problems with the speed, i just need to spot the error(s) in the algorythm. (I've been stareing at it for so long i can't see anything i've done wrong).

    If i do manage to fix it, i'll post my game with source thus far if anyone's interested.


    Any more help would by much appreciated (as was the help thus far).
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


  7. #7
    pathfinder NotLKH's Avatar
    Join Date
    Apr 2001
    Posts
    2,397
    Originally posted by SLH
    FYI the A* algorythm also projuces the best path, and is recognised by most academics as the fastest (according to numerus sources).
    perhaps you could post some links to sites describing this?


  8. #8

    Thread Starter
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051
    Originally posted by NotLKH
    perhaps you could post some links to sites describing this?

    Certainly.

    This Page has lots of links about the A* algorythm (as well as a few others).
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


  9. #9

    Thread Starter
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051
    I found the error with my distance-calculating part of my algorythm, so you can assume that part of the algorythm works correctly.

    However i'm still having trouble with the final calculation though...
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


  10. #10

    Thread Starter
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051
    Well, after a lot of searching, i found the problem.

    If you want to see it in useClick Here
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width