• API
• FAQ
• Tools
• Archive
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.
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.
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 }
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.

Top