class Tmx::Parser::Tmx
Parses the TMX formatted output from Tiled.
Attributes
options[R]
Public Class Methods
new(options)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 14 def initialize(options) @options = options end
Public Instance Methods
parse(contents)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 18 def parse(contents) results = Nokogiri::XML(contents) convert_to_hash(results) end
Private Instance Methods
convert_to_hash(xml)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 25 def convert_to_hash(xml) { "version" => map_attr(xml,"version").to_i, "orientation" => map_attr(xml,"orientation"), "width" => map_attr(xml,"width").to_i, "height" => map_attr(xml,"height").to_i, "tilewidth" => map_attr(xml,"tilewidth").to_i, "tileheight" => map_attr(xml,"tileheight").to_i, "properties" => properties(xml.xpath("/map")), "layers" => map_layers(xml), "tilesets" => map_tilesets(xml), "object_groups" => map_object_groups(xml), "image_layers" => map_image_layers(xml) } end
data_from_layer(layer)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 82 def data_from_layer(layer) layer_data = layer.xpath("data").text.strip if layer.xpath("data/@encoding").text == "base64" layer_data = Base64.decode64(layer_data) end if layer.xpath("data/@compression").text == "zlib" data = unpack_data zlib_decompress(layer_data) elsif layer.xpath("data/@compression").text == "gzip" data = unpack_data gzip_decompress(layer_data) elsif layer.xpath("data/@encoding").text == "base64" data = unpack_data(layer_data) elsif layer.xpath("data/@encoding").text == "csv" data = layer_data.split(",").map(&:to_i) else data = layer.xpath("data/tile").map { |tile| tile.xpath("@gid").text.to_i } end end
gzip_decompress(data)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 106 def gzip_decompress(data) Zlib::GzipReader.new(StringIO.new(data)).read end
layer_attr(layer,name,options)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 53 def layer_attr(layer,name,options) layer.xpath("@#{name}").text == "" ? options[:default] : layer.xpath("@#{name}").text end
map_attr(xml,name)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 41 def map_attr(xml,name) xml.xpath("/map/@#{name}").text end
map_image_layers(xml)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 206 def map_image_layers(xml) xml.xpath("map/imagelayer").map do |image_layer| { "name" => image_layer.xpath("@name").text, "width" => image_layer.xpath("@width").text.to_i, "height" => image_layer.xpath("@height").text.to_i } end end
map_layers(xml)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 57 def map_layers(xml) layers = [] xml.xpath("/map/layer").each do |layer| layer_hash = {} layer_hash["name"] = layer.xpath("@name").text layer_hash["width"] = layer.xpath("@width").text.to_i layer_hash["height"] = layer.xpath("@height").text.to_i layer_hash["type"] = layer_attr(layer,"type",default: "tilelayer") layer_hash["opacity"] = layer_attr(layer,"opacity",default: 1.0).to_f layer_hash["visible"] = to_boolean(layer.xpath("@visible").text) layer_hash["x"] = layer.xpath("@x").text.to_i layer_hash["y"] = layer.xpath("@y").text.to_i layer_hash["data"] = data_from_layer(layer) layer_hash["properties"] = properties(layer) layers.push layer_hash end layers end
map_object_groups(xml)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 160 def map_object_groups(xml) xml.xpath("map/objectgroup").map do |object_group| objects = object_group.xpath("object").map do |object| properties = { "name" => object.xpath("@name").text, "type" => object.xpath("@type").text, "x" => object.xpath("@x").text.to_i, "y" => object.xpath("@y").text.to_i, "width" => object.xpath("@width").text.to_i, "height" => object.xpath("@height").text.to_i, "visible" => to_boolean(object.xpath("@visible").text), "properties" => properties(object) } properties.merge(object_shape(object)) end { "name" => object_group.xpath("@name").text, "width" => object_group.xpath("@width").text.to_i, "height" => object_group.xpath("@height").text.to_i, "opacity" => (object_group.xpath("@opacity").text == "" ? 1.0 : object_group.xpath("@opacity").text.to_f), "objects" => objects } end end
map_tilesets(xml)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 126 def map_tilesets(xml) xml.xpath("map/tileset").map do |tileset| # Firstgid is usually set in the main file, # even if a tileset is read from a separate file. firstgid = tileset.xpath("@firstgid").text.to_i source = tileset.xpath("@source") if source && source.size > 0 this_dir = @options[:filename] ? File.dirname(@options[:filename]) : "." tileset_path = File.join(this_dir, source.text) contents = File.read(tileset_path) results = Nokogiri::XML(contents) tileset = results.xpath("tileset") end image = tileset.xpath("image") properties = { "firstgid" => firstgid || tileset.xpath("@firstgid").text.to_i, "name" => tileset.xpath("@name").text, "tilewidth" => tileset.xpath("@tilewidth").text.to_i, "tileheight" => tileset.xpath("@tileheight").text.to_i, "spacing" => tileset.xpath("@spacing").text.to_i, "margin" => tileset.xpath("@margin").text.to_i, "image" => image.xpath("@source").text, "imageheight" => image.xpath("@height").text.to_i, "imagewidth" => image.xpath("@width").text.to_i, # "imagetrans" is a color to treat as transparent, like "ff00ff" for magenta. "imagetrans" => image.xpath("@trans").text, "properties" => properties(xml) } end end
object_shape(object)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 188 def object_shape(object) if not object.xpath("ellipse").empty? { "shape" => "ellipse" } elsif not object.xpath("polyline").empty? points = object.xpath("polyline/@points").text.split(" ") { "shape" => "polyline", "points" => points } elsif not object.xpath("polygon").empty? points = object.xpath("polygon/@points").text.split(" ") { "shape" => "polygon", "points" => points } else x = object.xpath("@x").text.to_i y = object.xpath("@y").text.to_i width = object.xpath("@width").text.to_i height = object.xpath("@height").text.to_i { "shape" => "polygon", "points" => [ "#{x},#{y}", "#{x + width},#{y}", "#{x + width},#{y + height}", "#{x},#{y + height}" ] } end end
properties(xml)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 45 def properties(xml) properties = {} xml.xpath("properties/property").each do |property| properties[property.xpath("@name").text] = property.xpath("@value").text end properties end
to_boolean(text)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 122 def to_boolean(text) ![ "false", "0" ].include?(text) end
unpack_data(data)
click to toggle source
Convert the XML data format into a valid format in Ruby.
@see sourceforge.net/apps/mediawiki/tiled/index.php?title=Examining_the_map_format @see www.ruby-doc.org/core-2.0/String.html#method-i-unpack
V | Integer | 32-bit unsigned, VAX (little-endian) byte order
# File lib/tmx/parsers/tmx.rb, line 118 def unpack_data(data) data.unpack("V" * (data.length / 4)) end
zlib_decompress(data)
click to toggle source
# File lib/tmx/parsers/tmx.rb, line 102 def zlib_decompress(data) Zlib::Inflate.inflate(data) end