class Demiurge::Tmx::TmxLocation
A TmxLocation
is a special location that is attached to a tile layout, a TMX file. This affects the size and shape of the room, and how agents may travel through it. TmxLocations have X and Y coordinates (grid coordinates) for their positions.
@since 0.2.0
Public Class Methods
Get the default tile cache for newly-created TmxLocations. Demiurge
provides one by default which can be overridden.
@return [Demiurge::Tmx::TileCache] The current default TileCache for newly-created TmxLocations @since 0.3.0
# File lib/demiurge/tmx.rb, line 110 def self.default_cache @default_cache ||= ::Demiurge::Tmx::TmxCache.new @default_cache end
Set the default cache for newly-created TmxLocations.
@param cache [Demiurge::Tmx::TileCache] The tile cache for all subsequently-created TmxLocations @since 0.3.0
# File lib/demiurge/tmx.rb, line 119 def self.set_default_cache(cache) @default_cache = cache end
Public Instance Methods
For a TmxLocation's legal position, find somewhere not covered as a collision on the collision map.
@return [String] A legal position string within this location @since 0.2.0
# File lib/demiurge/tmx.rb, line 214 def any_legal_position entry = tile_cache_entry if entry["collision"] # We have a collision layer? Fabulous. Scan upper-left to lower-right until we get something non-collidable. (0...entry["width"]).each do |x| (0...entry["height"]).each do |y| if entry["collision"][y * tile_cache_entry["width"] + x] == 0 # We found a walkable spot. return "#{@name}##{x},#{y}" end end end # If we got here, there exists no walkable spot in the whole location. end # Screw it, just return the upper left corner. return "#{@name}#0,0" end
Get the tile cache for this Tmxlocation
@return [Demiurge::Tmx::TileCache] @since 0.3.0
# File lib/demiurge/tmx.rb, line 135 def cache @cache ||= self.class.default_cache end
Determine whether this coordinate location can accommodate a rectangular item of the given coordinate dimensions.
@since 0.2.0
# File lib/demiurge/tmx.rb, line 195 def can_accomodate_dimensions?(left_x, upper_y, width, height) return false if left_x < 0 || upper_y < 0 right_x = left_x + width - 1 lower_y = upper_y + height - 1 return false if right_x >= tile_cache_entry["width"] || lower_y >= tile_cache_entry["height"] return true unless tile_cache_entry["collision"] (left_x..right_x).each do |x| (upper_y..lower_y).each do |y| return false if tile_cache_entry["collision"][y * tile_cache_entry["width"] + x] != 0 end end return true end
Let's resolve any exits that go to other TMX locations.
@since 0.3.0
Demiurge::Location#finished_init
# File lib/demiurge/tmx.rb, line 142 def finished_init super exits = [] return unless @state["tile_layout_type"] == "manasource" # Go through the contents looking for locations zone_contents = self.zone.contents # ManaSource locations often store exits as objects in an # object layer. They don't cope with multiple locations that # use the same TMX file since they identify the destination by # the TMX filename. In Demiurge, we don't let them cross zone # boundaries to avoid unexpected behavior in other folks' # zones. tile_cache_entry["objects"].select { |obj| obj["type"].downcase == "warp" }.each do |obj| next unless obj["properties"] dest_map_name = obj["properties"]["dest_map"] dest_location = zone_contents.detect { |loc| loc.is_a?(::Demiurge::Tmx::TmxLocation) && loc.tile_cache_entry["tmx_name"] == dest_map_name } if dest_location entry = dest_location.tile_cache_entry dest_position = "#{dest_location.name}##{obj["properties"]["dest_x"]},#{obj["properties"]["dest_y"]}" src_x_coord = obj["x"] / tile_cache_entry["tilewidth"] src_y_coord = obj["y"] / tile_cache_entry["tileheight"] src_position = "#{name}##{src_x_coord},#{src_y_coord}" raise("Exit destination position #{dest_position.inspect} loaded from TMX location #{name.inspect} (TMX: #{tile_cache_entry["filename"]}) is not valid!") unless dest_location.valid_position?(dest_position) exits.push({ src_loc: self, src_pos: src_position, dest_pos: dest_position }) else @engine.admin_warning "Unresolved TMX exit in #{name.inspect}: #{obj["properties"].inspect}!", "location" => name, "properties" => obj["properties"] end end exits.each do |exit| exit[:src_loc].add_exit(from: exit[:src_pos], to: exit[:dest_pos]) end end
Set the tile cache for this specific TmxLocation
@param cache [Demiurge::Tmx::TileCache] @since 0.3.0
# File lib/demiurge/tmx.rb, line 127 def set_cache(cache) @cache = cache end
Return the tile object for this location
# File lib/demiurge/tmx.rb, line 233 def tile_cache_entry raise("A TMX location (name: #{@name.inspect}) must have a tile layout!") unless state["tile_layout_filename"] cache.tmx_entry(@state["tile_layout_type"], @state["tile_layout_filename"]) end
Return a TMX object's structure, for an object of the given name, or nil.
# File lib/demiurge/tmx.rb, line 239 def tmx_object_by_name(name) tile_cache_entry["objects"].detect { |o| o["name"] == name } end
Return the tile coordinates of the TMX object with the given name, or nil.
# File lib/demiurge/tmx.rb, line 244 def tmx_object_coords_by_name(name) obj = tmx_object_by_name(name) return nil unless obj [ obj["x"] / tile_cache_entry["tilewidth"], obj["y"] / tile_cache_entry["tileheight"] ] end
This checks the coordinate's validity, but not relative to any specific person/item/whatever that could occupy the space.
@return [Boolean] Whether the coordinate is valid @since 0.2.0
# File lib/demiurge/tmx.rb, line 184 def valid_coordinate?(x, y) return false if x < 0 || y < 0 return false if x >= tile_cache_entry["width"] || y >= tile_cache_entry["height"] return true unless tile_cache_entry["collision"] return tile_cache_entry["collision"][y * tile_cache_entry["width"] + x] == 0 end