TheoAllen

Theo - BFS Pathfinding

May 8th, 2014
429
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 6.57 KB | None | 0 0
  1. # =============================================================================
  2. # TheoAllen - Breadth-First Search Pathfinding
  3. # Version : 1.0
  4. # Contact : www.rpgmakerid.com (or) http://theolized.blogspot.com
  5. # (This script documentation is written in informal indonesian language)
  6. # =============================================================================
  7. ($imported ||= {})[:Theo_BFSPathfind] = true
  8. # =============================================================================
  9. # Change Logs:
  10. # -----------------------------------------------------------------------------
  11. # 2014.05.08 - Finished script
  12. # =============================================================================
  13. =begin
  14.  
  15.   Perkenalan :
  16.   Script ini adalah untuk menemukan jalan terpendek dari sebuah karakter/event
  17.   ke koordinat tujuan
  18.  
  19.   Cara penggunaan :
  20.   Pasang di bawah material namun diatas main.
  21.  
  22.   Gunakan script call pada set move route
  23.   find_path(x,y)
  24.  
  25.   Dimana x,y adalah koordinat tujuan.
  26.   Apabila jalan tidak ditemukan, maka karakter/event tidak akan bergerak
  27.  
  28.   Terms of use :
  29.   Credit gw, TheoAllen. Kalo semisal u bisa ngedit2 script gw trus jadi lebih
  30.   keren, terserah. Ane bebasin. Asal ngga ngeklaim aja. Kalo semisal mau
  31.   dipake buat komersil, jangan lupa, gw dibagi gratisannya.  
  32.  
  33. =end
  34. #==============================================================================
  35. # Tidak ada konfigurasi
  36. #==============================================================================
  37. # ** MapNode
  38. #------------------------------------------------------------------------------
  39. #  A node that represent tilemap passability
  40. #==============================================================================
  41. class MapNode
  42.   attr_accessor :parent   # Parent node
  43.   attr_accessor :visited  # Visited flag
  44.   attr_reader :nodes      # Child node
  45.   attr_reader :x          # X Coordinate
  46.   attr_reader :y          # Y Coordinate
  47.   # ---------------------------------------------------------------------------
  48.   # *) Initialize
  49.   # ---------------------------------------------------------------------------
  50.   def initialize(x,y)
  51.     @x = x
  52.     @y = y
  53.     @nodes = {}
  54.     @visited = false
  55.   end
  56.   # ---------------------------------------------------------------------------
  57.   # *) Make child node
  58.   # ---------------------------------------------------------------------------
  59.   def make_nodes(mapnodes, char)
  60.     dir = [2,4,6,8]
  61.     # Check all direction
  62.     dir.each do |d|
  63.       next unless char.passable?(x,y,d)
  64.       xpos = x
  65.       ypos = y
  66.       case d
  67.       when 2 # DOWN
  68.         ypos += 1
  69.       when 4 # LEFT
  70.         xpos -= 1
  71.       when 6 # RIGHT
  72.         xpos += 1
  73.       when 8 # UP
  74.         ypos -= 1
  75.       end
  76.       key = [xpos,ypos]
  77.       # Get the next noce
  78.       next_node = mapnodes[key]
  79.       if next_node.nil?
  80.         next_node = MapNode.new(xpos,ypos)
  81.         mapnodes[key] = next_node
  82.       end
  83.       # Set child node
  84.       self.nodes[d] = next_node
  85.     end
  86.   end
  87.  
  88. end
  89. #==============================================================================
  90. # ** Game_Character
  91. #------------------------------------------------------------------------------
  92. #  A character class with mainly movement route and other such processing
  93. # added. It is used as a super class of Game_Player, Game_Follower,
  94. # GameVehicle, and Game_Event.
  95. #==============================================================================
  96. class Game_Character
  97.   # ---------------------------------------------------------------------------
  98.   # *) Alias force move route
  99.   # ---------------------------------------------------------------------------
  100.   alias theo_pathfind_force_move force_move_route
  101.   def force_move_route(move_route)
  102.     route = Marshal.load(Marshal.dump(move_route))
  103.     theo_pathfind_force_move(route)
  104.   end
  105.   # ---------------------------------------------------------------------------
  106.   # *) Create entire map node
  107.   # ---------------------------------------------------------------------------
  108.   def create_mapnodes
  109.     @mapnodes = {}
  110.     # Scan entire map ~
  111.     for i in 0..$game_map.width
  112.       for j in 0..$game_map.height
  113.         key = [i,j]
  114.         node = @mapnodes[key]
  115.         if node
  116.           node.make_nodes(@mapnodes, self)
  117.         else
  118.           new_node = MapNode.new(i,j)
  119.           new_node.make_nodes(@mapnodes, self)
  120.           @mapnodes[key] = new_node
  121.         end
  122.       end
  123.     end
  124.   end
  125.   # ---------------------------------------------------------------------------
  126.   # *) Find Path
  127.   # ---------------------------------------------------------------------------
  128.   def find_path(tx,ty)
  129.     create_mapnodes
  130.     @target_findx = tx
  131.     @target_findy = ty
  132.     @queue = []
  133.     @queue.push(@mapnodes[[self.x,self.y]])
  134.     until @queue.empty?
  135.       bfsearch(@queue.shift)
  136.     end
  137.     @mapnodes.clear
  138.   end
  139.   # ---------------------------------------------------------------------------
  140.   # *) Breadth-First Seach algorithm
  141.   # ---------------------------------------------------------------------------
  142.   def bfsearch(node)
  143.     node.visited = true
  144.     dir = [2,4,8,6]
  145.     dir.each do |d|
  146.       next unless node.nodes[d]
  147.       next_node = node.nodes[d]
  148.       if next_node.x == @target_findx && next_node.y == @target_findy
  149.         next_node.parent = node
  150.         generate_route(next_node)
  151.         @queue.clear
  152.         return
  153.       end
  154.       next if next_node.visited
  155.       next_node.parent = node
  156.       next_node.visited = true
  157.       @queue.push(next_node)
  158.     end
  159.   end
  160.   # ---------------------------------------------------------------------------
  161.   # *) Generate move route
  162.   # ---------------------------------------------------------------------------
  163.   def generate_route(node)
  164.     list = []
  165.     loop do
  166.       break if node.parent.nil?
  167.       dir = get_dir(node, node.parent)
  168.       command = RPG::MoveCommand.new
  169.       command.code = dir/2
  170.       list.unshift(command)
  171.       node = node.parent
  172.     end
  173.     list.push(RPG::MoveCommand.new)
  174.     if !@move_route
  175.       route = RPG::MoveRoute.new
  176.       route.list = list
  177.       force_move_route(route)
  178.     else
  179.       @move_route.list.insert(@move_route_index+1, *list)
  180.     end
  181.   end
  182.   # ---------------------------------------------------------------------------
  183.   # *) Get direction
  184.   # ---------------------------------------------------------------------------
  185.   def get_dir(node, parent)
  186.     if node.y > parent.y
  187.       return 2
  188.     elsif node.x < parent.x
  189.       return 4
  190.     elsif node.x > parent.x
  191.       return 6
  192.     elsif node.y < parent.y
  193.       return 8
  194.     end
  195.   end
  196.  
  197. end
Advertisement
Add Comment
Please, Sign In to add comment