Advertisement
ForeverZer0

[RMXP] Simple Pathfinding

May 26th, 2011
562
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 4.34 KB | None | 0 0
  1. #===============================================================================
  2. # ** Pathfind
  3. #===============================================================================
  4.  
  5. class Pathfind
  6.  
  7.   ANGLES = [0, 45, 90, 135, 180, 225, 270, 315]
  8.   INDEX = [6, 9, 8, 7, 4, 1, 2, 3]
  9.  
  10.   attr_reader :character
  11.  
  12.   def initialize(character, x, y)
  13.     # Initialize required instance variables that the system needs.
  14.     @character, @x, @y = character, x, y
  15.     @route, @route_blocked = [], false
  16.     calculate_route
  17.   end
  18.  
  19.   def calculate_route
  20.     # Set up an intial route. This will be deviated from if object blocks path.
  21.     temp = [@character.x, @character.y]
  22.     until temp == [@x, @y]
  23.       move = next_move(temp[0], temp[1])
  24.       # Break loop if the method cannot calculate a route.
  25.       break if move == nil
  26.       # Add move code, then reset temp variable
  27.       @route.push(move)
  28.       temp = next_coordinates(temp[0], temp[1], move)
  29.     end
  30.   end
  31.  
  32.   def next_coordinates(x, y, dir)
  33.     # Returns the new coordinates of a successful move in given direction
  34.     return case dir
  35.     when 1 then [x - 1, y + 1]    # Down-Left
  36.     when 2 then [x, y + 1]        # Down
  37.     when 3 then [x + 1, y + 1]    # Down-Right
  38.     when 4 then [x - 1, y]        # Left
  39.     when 6 then [x + 1, y]        # Right
  40.     when 7 then [x - 1, y - 1]    # Up-Left
  41.     when 8 then [x, y - 1]        # Up
  42.     when 9 then [x + 1, y - 1]    # Up-Right
  43.     end
  44.   end
  45.  
  46.   def get_angle(x1, y1, x2, y2)
  47.     # Returns the angle between two points on the map.
  48.     angle = Math.atan2(y1 - y2, x2 - x1) * 180 / Math::PI
  49.     return (angle < 0) ? angle + 360 : angle
  50.   end
  51.  
  52.   def next_move(x, y)
  53.     # Returns the numerical "code" of which direction to make.
  54.     angle = get_angle(x, y, @x, @y)
  55.     value = ANGLES.find {|ang| (angle - ang.floor).abs < 45 }
  56.     i = ANGLES.index(value)
  57.     directions = [i, (i + 1) % 8, (i - 1) % 8].collect {|j| INDEX[j] }
  58.     # Attempt first coordinate, if that fails, attempts next closest two
  59.     directions.each {|d|
  60.       return d if @character.passable?(*(next_coordinates(x, y, d) + [d])) }
  61.   end
  62.  
  63.   def adapt_route
  64.     # Calculate move on the fly.
  65.     @character.make_move(next_move(@character.x, @character.y))
  66.   end
  67.  
  68.   def update
  69.     # If character is not moving, execute next move.
  70.     unless @character.moving?
  71.       @route_blocked ? @character.make_move(@route.shift) : adapt_route
  72.     end
  73.   end
  74.  
  75.   def complete?
  76.     # Returns true/false if the move route is finished
  77.     return @route.empty? || ((@character.x == @x) && (@character.y == @y))
  78.   end
  79.  
  80. end
  81.  
  82. #===============================================================================
  83. # ** Game_Map
  84. #===============================================================================
  85.  
  86. class Game_Map
  87.  
  88.   attr_accessor :pathfind
  89.  
  90.   alias zer0_pathfind_setup setup
  91.   def setup(map_id)
  92.     # Initialize update array for pathfinding.
  93.     @pathfind = []
  94.     zer0_pathfind_setup(map_id)
  95.   end
  96.  
  97.   alias zer0_pathfind_upd update
  98.   def update
  99.     # Update all pathfinders that are not complete.
  100.     unless @pathfind.empty?
  101.       # Update pathfinders, then remove any that are complete.
  102.       @pathfind.each {|pathfind| pathfind.update }
  103.       @pathfind.reject! {|pathfind| pathfind.complete? }
  104.     end
  105.     # Normal method
  106.     zer0_pathfind_upd
  107.   end
  108. end
  109.  
  110. #===============================================================================
  111. # ** Game_Character
  112. #===============================================================================
  113.  
  114. class Game_Character
  115.  
  116.   def pathfind(x, y)
  117.     # Adds this character's route to the map's pathfind update.
  118.     pathfinder = Pathfind.new(self, x, y)
  119.     # Remove any route from the update if it already exists for this character
  120.     $game_map.pathfind.reject! {|pathfind| pathfind.character == self }
  121.     # Add the route
  122.     $game_map.pathfind.push(pathfinder)
  123.   end
  124.  
  125.   def make_move(dir)
  126.     # Make a move using the passed number as a condition for direction.
  127.     case dir
  128.     when 1 then move_lower_left
  129.     when 2 then move_down(!@direction_fix)
  130.     when 3 then move_lower_right
  131.     when 4 then move_left(!@direction_fix)
  132.     when 6 then move_right(!@direction_fix)
  133.     when 7 then move_upper_left
  134.     when 8 then move_up(!@direction_fix)
  135.     when 9 then move_upper_right
  136.     end
  137.   end
  138. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement