class Demiurge::TiledLocation
A TiledLocation
is a location that uses x,y format for positions for a 2D grid in the location. Something like a TMX file defines a TiledLocation
, but so does an infinitely generated tiled space.
@since 0.3.0
Public Class Methods
Parse a tiled position string and return the X and Y tile coordinates
@param pos [String] The position string to parse @return [Array<Integer,Integer>] The x, y coordinates @since 0.2.0
# File lib/demiurge/location.rb, line 107 def self.position_to_coords(pos) loc, x, y = position_to_loc_coords(pos) return x, y end
Parse a tiled position string and return the location name and the X and Y tile coordinates
@param pos [String] The position string to parse @return [Array<String,Integer,Integer>] The location name and x, y coordinates @since 0.2.0
# File lib/demiurge/location.rb, line 117 def self.position_to_loc_coords(pos) loc, coords = pos.split("#",2) if coords x, y = coords.split(",") return loc, x.to_i, y.to_i else return loc, nil, nil end end
Public Instance Methods
Return the list of valid adjacent positions from this one
# File lib/demiurge/location.rb, line 232 def adjacent_positions(pos, options = {}) location, pos_spec = pos.split("#", 2) loc = @engine.item_by_name(location) x, y = pos_spec.split(",").map(&:to_i) shape = options[:shape] || "humanoid" [[x - 1, y], [x + 1, y], [x, y - 1], [x, y + 1]].select { |xp, yp| loc.can_accomodate_shape?(xp, yp, shape) } end
Return a legal position in this location
@return [String] A legal position string @since 0.3.0
# File lib/demiurge/location.rb, line 227 def any_legal_position "#{@name}#0,0" end
Determine whether this position can accomodate the given agent's shape and size.
@param agent [Demiurge::Agent] The agent being checked @param position [String] The position being checked @return [Boolean] Whether the position can accomodate the agent @since 0.2.0
# File lib/demiurge/location.rb, line 172 def can_accomodate_agent?(agent, position) loc, x, y = TiledLocation.position_to_loc_coords(position) raise "Location #{@name.inspect} asked about different location #{loc.inspect} in can_accomodate_agent!" if loc != @name shape = agent.state["shape"] || "humanoid" can_accomodate_shape?(x, y, shape) end
Whether the location can accomodate an object of this size.
@param left_x [Integer] The lower (leftmost) X coordinate @param upper_y [Integer] The higher (upper) Y coordinate @param width [Integer] How wide the checked object is @param height [Integer] How high the checked object is @return [Boolean] Whether the object can be accomodated @since 0.3.0
# File lib/demiurge/location.rb, line 197 def can_accomodate_dimensions?(left_x, upper_y, width, height) true end
Determine whether this coordinate location can accomodate an item of the given shape.
For now, don't distinguish between walkable/swimmable or whatever, just say a collision value of 0 means valid, everything else is invalid.
@param left_x [Integer] The lower (leftmost) X coordinate @param upper_y [Integer] The higher (upper) Y coordinate @return [Boolean] Whether the object can be accomodated @since 0.3.0
# File lib/demiurge/location.rb, line 212 def can_accomodate_shape?(left_x, upper_y, shape) case shape when "humanoid" return can_accomodate_dimensions?(left_x, upper_y, 2, 1) when "tiny" return can_accomodate_dimensions?(left_x, upper_y, 1, 1) else raise "Unknown shape #{shape.inspect} passed to can_accomodate_shape!" end end
When an item changes position in a TiledLocation
, check if the new position leads out an exit. If so, send them where the exit leads instead.
@param item [String] The item changing position @param old_pos [String] The position string the item is moving from @param new_pos [String] The position string the item is moving to @return [void] @since 0.2.0
Demiurge::Container#item_change_position
# File lib/demiurge/location.rb, line 136 def item_change_position(item, old_pos, new_pos) exit = @state["exits"].detect { |e| e["from"] == new_pos } return super unless exit # No exit? Do what you were going to. # Going to hit an exit? Cancel this motion and enqueue an # intention to do so? Or just send them through? If the former, # it's very hard to unblockably pass through an exit, even if # that's what's wanted. If the latter, it's very hard to make # going through an exit blockable. # Eh, just send them through for now. We'll figure out how to # make detecting and blocking exit intentions easy later. item_change_location(item, old_pos, exit["to"]) end
Whether the coordinate is valid
@param x [Integer] The X coordinate @param y [Integer] The Y coordinate @return [Boolean] Whether the coordinate is valid @since 0.3.0
# File lib/demiurge/location.rb, line 185 def valid_coordinate?(x,y) true end
This just determines if the position is valid at all. It does not check walkable/swimmable or even if it's big enough for a humanoid to stand in.
@param pos [String] The position being checked @return [Boolean] Whether the position is valid @since 0.2.0
# File lib/demiurge/location.rb, line 159 def valid_position?(pos) return false unless pos[0...@name.size] == @name return false unless pos[@name.size] == "#" x, y = pos[(@name.size + 1)..-1].split(",", 2).map(&:to_i) valid_coordinate?(x, y) end