[XP] Advanced Pathfinding

Started by ForeverZer0, May 30, 2011, 04:00:31 pm

Previous topic - Next topic

ThallionDarkshine

Heretic - your added code actually made a new error in the demo. When the event is moving, and its path is blocked, it first sets paths[0] equal to a new instance of pathfinding. Then your code sets paths to [], and finally the collision retry code tries to access one of the variables of paths[0].

ForeverZer0 - Your getCurrent code is very confusing. I replaced it with 6 lines of code getting the node in open set with the lowest score.

ForeverZer0

You do realize that that method is the actual implementation of the A* algorithm?
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

ThallionDarkshine

Oh, sorry. I just went to the Wikipedia page and found that you needed to get the node with the lowest score.

Heretic86

Quote from: ThallionDarkshine on May 16, 2012, 10:35:07 pm
Heretic - your added code actually made a new error in the demo. When the event is moving, and its path is blocked, it first sets paths[0] equal to a new instance of pathfinding. Then your code sets paths to [], and finally the collision retry code tries to access one of the variables of paths[0].

...


Youre right.  I went back, tried to rethink it out and came up with the same solution, just in a different spot.

I was able to recreate the problem, but hopefully I just had it in the wrong spot.  Try putting @paths = [] right after @stop_count = 0 in def move_type_custom.
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

ThallionDarkshine

Alright, I'll try and see if it works.

Darian

July 18, 2012, 09:53:57 am #45 Last Edit: July 18, 2012, 09:55:00 am by Darian
Great script!
It works perfectly for me in an event and when using it via "call script" in the RMXP.
I'm new to the RGSS and I'm currently writing one of my first own scripts (a battle system).

So I would like to use this cool Pathfinding script there, but I don't know how to include it.
For my own script I've a class containing an initialize-methode and an update-methode. But where and how do I have to include this Pathfinding script? (I've of course pasted it above MAIN and as said before it works perfectly inside an event calling it.)

Could you please give me the lines so I can use the
pathfind(x, y, id, range, s, f)

like in an event?

Thank you! :)

ForeverZer0

Take a peek at the Interpreter section of script. There you will see some examples of how to use pathfinding without making the call with the event command. I'm on my phone at the moment, but I can offer more detailed help later if you still need it.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Darian

Thank you! I think I found it.
And it works :)

#Pathfind.new(Node.new(x, y), *args)
Pathfind.new(Node.new(8, 6), 13)


Two questions:
1) How can implement the success and fail argument there?
2) Following situation:
Legend:
O = free tile
S = starting point
E = end point
P = walked path

OOS
OOO
EOO


So when executing this situation, then the path is the following:
OOS
OOP
EPP

So the event goes straight down and then left. I would like to see rather a diagonal pattern:

OOS
OPO
EOO


How can I enable this? I would like to have the most direct way, especially when walking short distances. It seems to be that the algorithm doesn't include diagonal movement? How can I implement this :)

Thanks for your quick help!





ForeverZer0

The script does not support 8-directional movement by default, only 4. It would take a sizable edit to add the functionality. It would not be especially difficult, but would require quite a few additional checks when the system is laying out the path, and adding commands for the diagonal movements based off what was possible.

I really don't write scripts anymore, so I am sorry to say that I won't be making the edits. After the release of ARC, I may create a ARC port of the script (if we don't include pathfinding functionality in the default scripts), and in that case I will likely add the ability, but that isn't anything to plan on.

It wouldn't be super hard to add the functionality if you or another scripter would like to take a stab at it. Find the area in the script where it builds the move routes, and add the appropriate checks and commands. All it requires is an understanding of how RPG::MoveRoutes and map passability work, you don't need to understand the algorithm or the more advanced logic of the script to do it. I can provide advice to anyone who would like to try it.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Darian

July 18, 2012, 05:26:25 pm #49 Last Edit: July 18, 2012, 06:18:31 pm by Darian
Thanks again for the fast reply!
I fully understand your situation.
Okay, so before I will start scripting or ask someone else do you - or someone else here - know another pathfinding script which supports 8 directional movement?

Foreverzer0, could you please just tell me how I can add the option for the success argument here (when calling it not via an event):
#Pathfind.new(Node.new(x, y), *args)
Pathfind.new(Node.new(8, 6), 13)


That would help me a bit :)

EDIT: I got it!! :)
			s = Proc.new { print 'Goal Reached!'}
f = Proc.new { print 'Failed!' }
#pathfind(x, y, id, range, s, f)
Pathfind.new(Node.new(Mouse.tile_x, Mouse.tile_y), 13, 0, s, f)

Nevertheless a pathfinding system with 8 movement would be cool. If anyone knows something where to find it, please let me know.


ForeverZer0

Oops, yes, I forgot to answer your original question. :facepalm:

You need to create a Proc object and pass it as an argument. The Proc can be anything you wish really, you can have it call a method, change a variable, etc.

I do not know what you want to do, so its a bit hard to tell you what argument to pass, but here would be an example:
Lets say that I want to flip a switch whenever the pathfind successfully completes:

Pathfind.new(Node.new(8, 6), 13, 0, Proc.new { $game_switches[1] = true })

The node is the coordinates, 13 is the event ID, 0 is the range, and the Proc is the procedure that will be executed on a successful route completion.

I am not aware of a pathfinding script that supports 8-directional movement, but to be honest I have never really looked into any others, so that does not mean to much.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Darian

Great, Thank you!! I'll try it out :)

Darian

July 20, 2012, 11:36:36 am #52 Last Edit: July 20, 2012, 11:46:38 am by Darian
I'm now trying "to do waypoints" with your script.

Example: I simply put two commands in two lines like this:

Pathfind.new(Node.new(Mouse.tile_x, Mouse.tile_y), @char_id)
Pathfind.new(Node.new(Mouse.tile_x, Mouse.tile_y+6), @char_id)

So it works well, the character goes first to the tile where the mouse is and then 6 tiles more south.

But when executing the same piece of code later again in my script, the character just doesn't move. I can't explain this - what is wrong?

EDIT: Moreover is there perhaps another way to do waypoints with your scripts?

ForeverZer0

I don't know, I can't see what extactly the situation is when the call is made.
One thing to keep in mind, if the "range" is set to 0, the destination tile must be passable, and the route must be open at the point of the call. If its not, nothing happens.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Darian

Ok for better explaining I modified your script game example and uploaded it here:
http://www.filedropper.com/advancedpathfindingdarian

Here's the script:

class Cycle
 
  def initialize
    @s = Proc.new { print 'Waypoint Reached!'}
    @f = Proc.new { print 'Failed!  ' }
    @range = 0
    @first_switch = "on"
  end
 
  def update
   
    if @first_switch == "on"
      p "phase for the first two waypoints"
      Pathfind.new(Node.new(2, 3), 1, @range, @s, @f)
      Pathfind.new(Node.new(3, 6), 1, @range, Proc.new { @second_switch = "on" }, @f)
      @first_switch = "off"
      #@second_switch = "on" # WHEN activating this line, the third waypoint works.
    end
   
    if @second_switch == "on"
      p "phase for the third waypoint"
      Pathfind.new(Node.new(4, 10), 1, @range, @s, @f)
      @second_switch = "off"
    end
   
  end

end


I've implented the Cycle in the Scene_Map (and update Methode there).
There are 3 waypoints on the map: These three little sand spots which will be visited from north to south.
The third waypoint won't be reached. It will only work when I set the switch manually in line 17 (removing the comment).
Why is this? :)

Thank you very much for your time!!

ForeverZer0

A simpler method to what you want would be to simply set new Pathfinds as the success procs:

    s2 = Proc.new { Pathfind.new(Node.new(4, 10), 1, 0) }
    s1 = Proc.new { Pathfind.new(Node.new(3, 6), 1, 0, s2) }
    Pathfind.new(Node.new(2, 3), 1, 0, s1)


I tried this, and it appears to be some type of problem with calling consecutive paths. Something isn't quite making sense to me, though. I used the above code, and it worked for the first two points, but didn't do anything for the third. I replaced the "s2" with a simple proc to display some text, and that worked, but when I replaced it with another Pathfind, it does nothing. It may be that the check for setting up a new path is already passed when the success proc is called, and it would require a wiat of a frame before continuing. Not sure I didn't test that in-depth. If I get some later, I will take a second look.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Darian

Yes, I had the same experience. The third pathfinding order doesn't work. I tried several variants with switches, but it doesn't help either.

It would be great if you could try something with your more advanced scripting skills :)
Thank you!

Darian

I found something! :)
With cases it seems to work:

class Cycle
 
  def initialize
    @s = Proc.new { print 'Waypoint Reached!'}
    @f = Proc.new { print 'Failed!  ' }
    @range = 0
    @phase = 1
  end
 
  def update

    case @phase
   
    when 1
      Pathfind.new(Node.new(2, 3), 1, @range, @s, @f)
      @phase = 2
     
    when 2 
      Pathfind.new(Node.new(3, 6), 1, @range, @s, @f)
      @phase = 3
     
    when 3
      Pathfind.new(Node.new(4, 10), 1, @range, @s, @f)
      @phase = 4
    end
   
  end

end

Now it works. But strangely, though it's phase = 4 at the end the character keeps still walking between the last two waypoints. Could you explain this? That's strange...

ForeverZer0

The pathfinds will stack within the character's path variable, so you actually don't need a condition setting phases or anything.
This works within a script call, although the repeat of the last two steps persists...
Pathfind.new(Node.new(2, 3), 1, 0)
Pathfind.new(Node.new(3, 6), 1, 0)
Pathfind.new(Node.new(4, 10), 1, 0)


For some reason, it appears the path is not being removed before the next begins or something. I'll have to look into it.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Darian

Yes that makes sense to me, that could be the reason!
Would be cool if you could have a look :)
Thank you!