Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

[XP] Yet Another A* Pathfinding Script! (NEW: Version 1.4)

could this be used to make events find a path to the player/other events?
or to co-ordinates stored by variables?
and can it be used to make an event line itself up with the player/other events?(as if it were lining up to shoot it)
if so, how?
 
You should check it out straight from the demo, its really good at allowing Events to track the player and visa versa.

If you wanted to do something like what you're talking about, I'm not sure how to do it in the script. You'd probably have to track the player's X, and lock the Y by doing something like this...

Code:
x = $game_player.x
y = 5
e = Node.new(x, y)
ch = $game_player     
$path = A_Star_Pathfinder.new
$path.setup(e, ch, 1)
$path.calculate_path
$path.generate_path

Meaning that the event's Y will always stay on 5 (or whatever number you specify), yet it'd be constantly tracking the player's X and moving as the player move. You'd still probably want to keep the event's settings with Lock Facing checked, so its always facing up as its shooting.
 

Tindy

Sponsor

Great script.  Took me a bit to think of the possibilities, but now that I've got that...

What would you input to make a different character move?  I've tried everything, but I can't quite get it. 

I assume it's on line ch: $game_player, and I assume I would change $game_player to something, but I don't know what.

I've tried just about everything I can think of.  So if it's EV003, I would change it too....?
 
I'll answer it for you then. You can use get_close. This variable (boolean) makes the script try to create a path to surrounding tiles if the tile mentioned in the path is not availeble. I think that actually suites what you are wanting right?

This is the setup method you are looking for:

Code:
 #--------------------------------------------------------------------------
  # * Setup Initial Values for Variables
  #     goal_node : A Node representing the end point
  #     character : The character that'd use the result of pathfinding
  #     range     : The size of the goal area, 0 means the goal is the
  #                 node, 1 means within 1 tile around goal, etc.
  #     close     : If true the character will try to get as close as
  #                 possible to path if it isn't found.
  #     reach     : A Proc that will be called when the goal is reached
  #     fail      : A proc that will be called if no path was found
  #--------------------------------------------------------------------------
  def setup(goal_node, character, range = 0, close = false,
            reach = nil, fail = nil)

The header pretty much gives all the information you need - I suppose.
 
Hello everyone. A little bump at last. I have been pretty busy for the last months and I apologize for the lack of updates and for not answering your questions. I thank Me(tm) and Kain for their efforts on that end. I've been working on a new version, but it's been mostly small improvements that still don't amount to a new version. For 1.5 I want to take pathfinding calculation out of the loop (probably as an alternative update method to call every frame) so the calculation pause could be better controlled by your code, this allows calculating paths "in the background" and allow doing something else instead of just pausing everything. A change like that might take a while to implement and it's not a priority at the moment. If you have any suggestions for other changes, feel free to share them.

Anyway, to answer your questions:

Twin Matrix":1o9lwuxu said:
Bump for my question.

It's actually a simple question though it looks large.. I would appreciate it if someone could read it.

It's a few posts ^.

Use get_close to have the character get as close as possible to the goal. This is unlikely to fail which means the target might still be many tiles away and yet the character moves only a few tiles to get closer. You could have a reach method to be called where you check if the other character in range and then do what you want. If reach methods sound complex to you then create dummy ones like lambda { $game_switches[xxx] = true } and have the actual processing in some common event activated by the switch.

Goal Area is different. Instead of having a goal that's only one tile, you could have a circular area around the goal node by specifying the range when calling the setup method. A range of 1 means 1 tile around the goal and so on. Finding a goal area could fail, but it's useful for stuff like getting a character to move into the vicinity of another character or event without being precise or dealing with other characters not being passable.

So like I said, call setup setting the close argument to true (4th argument), and supply a reach method where you check if goal is actually within reach, if not you could teleport. You could also provide a failure method that teleports as well, just in case.

Now how you handle teleportation is up to you. Like I said, you could use a common event and take the code out of the reach method, but the complexity might arise when trying to know where to teleport and you don't know where the goal is (e.g. a moving character). I don't know how your game works so I can't recommend the best way to do it. It might involve scanning tiles around goal for passability, or specifying certain disconnected areas or rooms on map and having one teleport spot in each, teleporting to the spot closest to the goal, or some different way that makes sense in the context of your game. It's not really within the scope of this script.

I hope that made sense, or was helpful in a way. I generally wouldn't ask people to do that, but I advise you to study the script. Even if you're not a scripter or don't want to bother with the details, skimming it to get a general idea of how it works (just read the comments) will be greatly beneficial to understand how to utilize it in your game. I provide simple shortcuts for most general uses like moving a character from A to B, but to get the most from a script like this you need a general understanding of what goes behind the scenes. This article is a good starting point. I'm not saying that to discourage you from asking me questions :P, I just thought that for your complex use of some script it pays to understand the cost of what you're doing (e.g. calculating many paths and checking if all failed... scary!)

etheon":1o9lwuxu said:
Just a question; wouldn't get a better average running-time (i.e.: O(nlogn)) with a binary tree implementation of your heap instead of an array implementation? Though Ruby arrays are different from conventional array, so I don't know...

Heap insertion and removal are O(logn) operations. It doesn't depend on whether you use a tree or an array. With an array binary heap, you could calculate children directly (2 * i and 2 * i + 1), and the minimum/maximum element is the first element so you never have to iterate over array elements to get O(n) behavior. Arrays might even be faster because there's less reference overhead and improved memory locality.

dario8676: I did implement your request but since I'm not releasing anything yet I might as well share it for your benefit. Replace the generate_path method with the following:

Code:
  #--------------------------------------------------------------------------
  # * Generate the Path by Following Parents and Return it 
  #   as RPG::MoveRoute
  #     follow :  If true the path is assigned to the character as a
  #               forced move route.
  #     steps  :  Actual number of steps to take, -1 means entire path
  #--------------------------------------------------------------------------
  def generate_path(follow = true, steps = -1)
    # There's no path to generate if no path was found
    if !@found
      return
    end
    # Create a new move route that isn't repeatable
    @route = RPG::MoveRoute.new
    @route.repeat = false
    # Generate path by starting from goal and following parents
    node = @goal_node
    code = 0    # Movement code for RPG::MoveCommand
    while node.parent
      # Get direction from parent to node as RPG::MoveCommand
      direction = get_direction(node.parent.x, node.parent.y, node.x, node.y)
      case direction
        when 2 # Up
          code = 4
        when 4 # Left
          code = 3
        when 6 # Right
          code = 2
        when 8 # Down
          code = 1
      end
      # Add movement code to the start of the array
      @route.list.unshift(RPG::MoveCommand.new(code)) if code != 0
      node = node.parent
    end
    if steps > -1
      @route.list = @route.list[0, steps]
      if @route.list[-1] and @route.list[-1].code != 0
        @route.list.push(RPG::MoveCommand.new)
      end
    end
    # If the path should be assigned to the character
    if follow and !@route.list.empty?
      @character.add_path(self)
    end
    # Return the constructed RPG::MoveRoute
    return @route
  end
end

Now you can call it with a number of steps to be followed: path.generate_path(true, 4).
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top