Class: Demiurge::Tmx::TmxLocation

Inherits:
Demiurge::TiledLocation show all
Defined in:
lib/demiurge/tmx.rb

Overview

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

Constant Summary

Constants inherited from ActionItem

ActionItem::ACTION_LEGAL_KEYS

Instance Attribute Summary

Attributes inherited from StateItem

#engine, #name

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Demiurge::TiledLocation

#adjacent_positions, #can_accomodate_agent?, #can_accomodate_shape?, #item_change_position, position_to_coords, position_to_loc_coords, #valid_position?

Methods inherited from Location

#add_exit, #adjacent_positions, #can_accomodate_agent?, #exits, #initialize, #location, #location_name, #valid_position?, #zone, #zone_name

Methods inherited from Container

#can_accomodate_agent?, #contents, #contents_names, #ensure_contains, #ensure_does_not_contain, #initialize, #intentions_for_next_step, #item_change_location, #item_change_position, #move_item_inside, #receive_offer

Methods inherited from ActionItem

#__state_internal, #get_action, #get_actions_with_tags, #initialize, #intentions_for_next_step, #location, #location_name, #position, #register_actions, #run_action, #zone, #zone_name

Methods inherited from StateItem

#agent?, from_name_type, #get_structure, #initialize, #intentions_for_next_step, #state, #state_type, #zone?

Constructor Details

This class inherits a constructor from Demiurge::Location

Class Method Details

.default_cacheDemiurge::Tmx::TileCache

Get the default tile cache for newly-created TmxLocations. Demiurge provides one by default which can be overridden.

Returns:

  • (Demiurge::Tmx::TileCache)

    The current default TileCache for newly-created TmxLocations

Since:

  • 0.3.0



110
111
112
113
# File 'lib/demiurge/tmx.rb', line 110

def self.default_cache
  @default_cache ||= ::Demiurge::Tmx::TmxCache.new
  @default_cache
end

.set_default_cache(cache) ⇒ Object

Set the default cache for newly-created TmxLocations.

Parameters:

  • cache (Demiurge::Tmx::TileCache)

    The tile cache for all subsequently-created TmxLocations

Since:

  • 0.3.0



119
120
121
# File 'lib/demiurge/tmx.rb', line 119

def self.set_default_cache(cache)
  @default_cache = cache
end

Instance Method Details

For a TmxLocation's legal position, find somewhere not covered as a collision on the collision map.

Returns:

  • (String)

    A legal position string within this location

Since:

  • 0.2.0



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/demiurge/tmx.rb', line 213

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

#cacheDemiurge::Tmx::TileCache

Get the tile cache for this Tmxlocation

Returns:

  • (Demiurge::Tmx::TileCache)

Since:

  • 0.3.0



135
136
137
# File 'lib/demiurge/tmx.rb', line 135

def cache
  @cache ||= self.class.default_cache
end

#can_accomodate_dimensions?(left_x, upper_y, width, height) ⇒ Boolean

Determine whether this coordinate location can accommodate a rectangular item of the given coordinate dimensions.

Returns:

  • (Boolean)

Since:

  • 0.2.0



194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/demiurge/tmx.rb', line 194

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

#finished_initObject

Let's resolve any exits that go to other TMX locations.

Since:

  • 0.3.0



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# 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
      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_cache(cache) ⇒ Object

Set the tile cache for this specific TmxLocation

Parameters:

  • cache (Demiurge::Tmx::TileCache)

Since:

  • 0.3.0



127
128
129
# File 'lib/demiurge/tmx.rb', line 127

def set_cache(cache)
  @cache = cache
end

#tile_cache_entryObject

Return the tile object for this location

Since:

  • 0.2.0



232
233
234
235
# File 'lib/demiurge/tmx.rb', line 232

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

#tmx_object_by_name(name) ⇒ Object

Return a TMX object's structure, for an object of the given name, or nil.

Since:

  • 0.2.0



238
239
240
# File 'lib/demiurge/tmx.rb', line 238

def tmx_object_by_name(name)
  tile_cache_entry["objects"].detect { |o| o["name"] == name }
end

#tmx_object_coords_by_name(name) ⇒ Object

Return the tile coordinates of the TMX object with the given name, or nil.

Since:

  • 0.2.0



243
244
245
246
247
# File 'lib/demiurge/tmx.rb', line 243

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

#valid_coordinate?(x, y) ⇒ Boolean

This checks the coordinate's validity, but not relative to any specific person/item/whatever that could occupy the space.

Returns:

  • (Boolean)

    Whether the coordinate is valid

Since:

  • 0.2.0



183
184
185
186
187
188
# File 'lib/demiurge/tmx.rb', line 183

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