From 9fcb7f3d6e30bc40f0157e7ead2b0edc529aa664 Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Fri, 25 Oct 2019 11:43:07 -0500 Subject: [PATCH] Crude path following implemented --- lib/entity.rb | 11 +++++++ lib/map.rb | 2 +- lib/pathfinding/base_pathfinder.rb | 52 ++++++++++++++++++++---------- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/lib/entity.rb b/lib/entity.rb index 7f8af7b..f6fbfa1 100644 --- a/lib/entity.rb +++ b/lib/entity.rb @@ -25,6 +25,7 @@ class IMICRTS @position = position @angle = angle @director = director + @speed = 0.5 @radius = 32 / 2 @target = nil @@ -41,6 +42,8 @@ class IMICRTS @goal_color = Gosu::Color.argb(175, 25, 200, 25) @target_color = Gosu::Color.argb(175, 200, 25, 25) + + @orders = [] end def serialize @@ -96,6 +99,7 @@ class IMICRTS rotate_towards(@target) if @target && @movement if @movement + follow_path end end @@ -107,6 +111,13 @@ class IMICRTS @on_tick = block end + def follow_path + if @pathfinder && node = @pathfinder.path_current_node + @pathfinder.path_next_node if @pathfinder.at_current_path_node?(@position) + @position -= (@position.xy - node.tile.position.xy).normalized * @speed + end + end + def selected_draw draw_radius draw_gizmos diff --git a/lib/map.rb b/lib/map.rb index f6ee58d..a4bf5b9 100644 --- a/lib/map.rb +++ b/lib/map.rb @@ -1,6 +1,6 @@ class IMICRTS class Map - attr_reader :tile_size, :tiles, :ores + attr_reader :tile_size, :tiles, :ores, :width, :height def initialize(map_file:) @tiled_map = TiledMap.new(map_file) diff --git a/lib/pathfinding/base_pathfinder.rb b/lib/pathfinding/base_pathfinder.rb index 71412bd..12aa27f 100644 --- a/lib/pathfinding/base_pathfinder.rb +++ b/lib/pathfinding/base_pathfinder.rb @@ -39,23 +39,25 @@ class IMICRTS @created_nodes = 0 @nodes = [] @path = [] - @tiles = @map.tiles.values.map { |columns| columns.values }.flatten.select { |tile| tile } + @tiles = @map.tiles @visited = Hash.new do |hash, value| hash[value] = Hash.new {|h, v| h[v] = false} end @depth = 0 - @max_depth = @tiles.size + @max_depth = @map.width * @map.height @seeking = true - position = entity.position.clone - position.x, position.y = position.x.floor, position.y.floor - position /= @map.tile_size + @position = entity.position.clone + @position.x, @position.y = @position.x.floor, @position.y.floor + @position /= @map.tile_size - @current_node = create_node(position.x, position.y, nil) + @path_current_node = 0 + + @current_node = create_node(@position.x, @position.y, nil, 0) unless @current_node - puts "Failed to find path!" if Setting.enabled?(:debug_mode) + puts "Unable to find path as position is not a traversable tile for :#{@entity.name}!" if Setting.enabled?(:debug_mode) return end @@ -68,6 +70,22 @@ class IMICRTS self.class.cache_path(self) if @path.size > 0 && true#Setting.enabled?(:debug_cache_paths) end + def path_current_node + @path[@path_current_node] + end + + def path_next_node + @path_current_node += 1 + end + + def at_current_path_node?(position) + if node = path_current_node + position.distance(node.tile.position) < @map.tile_size / 2 + else + true + end + end + # Checks if Map still has all of paths required tiles def valid? valid = true @@ -86,8 +104,8 @@ class IMICRTS seek end - if @depth >= @max_depth - puts "Failed to find path from: #{@source.x}:#{@source.y} (#{@map.grid.dig(@source.x,@source.y).element.class}) to: #{@goal.position.x}:#{@goal.position.y} (#{@goal.element.class}) [#{@depth}/#{@max_depth} depth]" if Setting.enabled?(:debug_mode) + if @depth >= @max_depth || (@path.size == 0 && @depth < 0) + puts "Failed to find path from: #{@position.x}:#{@position.y} to: #{@goal.x}:#{@goal.y} [#{@depth}/#{@max_depth} depth]" if Setting.enabled?(:debug_mode) end end @@ -96,7 +114,7 @@ class IMICRTS end def seek - unless @current_node && @map.tiles.dig(@goal.x, @goal.y) + unless @current_node && @tiles.dig(@goal.x, @goal.y) @seeking = false return end @@ -161,7 +179,7 @@ class IMICRTS end def create_node(x, y, parent, cost = 1.0) - return unless tile = @map.tiles.dig(x, y) + return unless tile = @tiles.dig(x, y) return unless tile.type == @travels_along return if tile.entity return if @visited.dig(x, y) @@ -200,27 +218,27 @@ class IMICRTS end def node_above?(node = @current_node) - node && @map.tiles.dig(node.tile.grid_position.x, node.tile.grid_position.y - 1) + node && @tiles.dig(node.tile.grid_position.x, node.tile.grid_position.y - 1) end def node_below?(node = @current_node) - node && @map.tiles.dig(node.tile.grid_position.x, node.tile.grid_position.y + 1) + node && @tiles.dig(node.tile.grid_position.x, node.tile.grid_position.y + 1) end def node_above_left?(node = @current_node) - node && @map.tiles.dig(node.tile.grid_position.x - 1, node.tile.grid_position.y - 1) + node && @tiles.dig(node.tile.grid_position.x - 1, node.tile.grid_position.y - 1) end def node_above_right?(node = @current_node) - node && @map.tiles.dig(node.tile.grid_position.x + 1, node.tile.grid_position.y - 1) + node && @tiles.dig(node.tile.grid_position.x + 1, node.tile.grid_position.y - 1) end def node_below_left?(node = @current_node) - node && @map.tiles.dig(node.tile.grid_position.x - 1, node.tile.grid_position.y + 1) + node && @tiles.dig(node.tile.grid_position.x - 1, node.tile.grid_position.y + 1) end def node_below_right?(node = @current_node) - node && @map.tiles.dig(node.tile.grid_position.x + 1, node.tile.grid_position.y + 1) + node && @tiles.dig(node.tile.grid_position.x + 1, node.tile.grid_position.y + 1) end end end