SHARE
TWEET

[RMXP] Simple Pathfinding

ForeverZer0 May 26th, 2011 431 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top