tmx 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +15 -10
- data/.rspec +2 -0
- data/Gemfile +8 -2
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/lib/tmx.rb +52 -13
- data/lib/tmx/layer.rb +4 -73
- data/lib/tmx/map.rb +11 -143
- data/lib/tmx/parsers/json.rb +24 -0
- data/lib/tmx/parsers/parsers.rb +30 -0
- data/lib/tmx/parsers/tmx.rb +145 -0
- data/lib/tmx/parsers/unknown.rb +24 -0
- data/lib/tmx/tile_set.rb +4 -34
- data/lib/tmx/version.rb +1 -1
- data/spec/features/json_format_spec.rb +76 -0
- data/spec/features/xml_format_spec.rb +84 -0
- data/spec/fixtures/map.json +39 -0
- data/spec/fixtures/map_csv.tmx +25 -0
- data/spec/fixtures/map_gzip.tmx +14 -0
- data/spec/fixtures/map_uncompressed.tmx +14 -0
- data/spec/fixtures/map_xml.tmx +205 -0
- data/spec/fixtures/map_zlib.tmx +17 -0
- data/spec/spec_helper.rb +16 -49
- data/tmx.gemspec +18 -22
- metadata +54 -70
- data/README.markdown +0 -92
- data/Rakefile +0 -11
- data/data/door.png +0 -0
- data/data/dude.png +0 -0
- data/data/test-tiles.png +0 -0
- data/data/test.tmx +0 -62
- data/examples/example-chingu.rb +0 -114
- data/lib/tmx/coder.rb +0 -39
- data/lib/tmx/coder/base64.rb +0 -13
- data/lib/tmx/coder/gzip.rb +0 -21
- data/lib/tmx/map/tile_cache.rb +0 -83
- data/lib/tmx/map/xml_loader.rb +0 -41
- data/lib/tmx/nokogiri_additions.rb +0 -56
- data/lib/tmx/object_group.rb +0 -30
- data/spec/coder_spec.rb +0 -29
- data/spec/map_spec.rb +0 -50
- data/spec/nokogiri_spec.rb +0 -5
- data/spec/object_group_spec.rb +0 -41
@@ -0,0 +1,30 @@
|
|
1
|
+
module Tmx
|
2
|
+
|
3
|
+
#
|
4
|
+
# This module defines the parsers for the formats of various
|
5
|
+
# TMX output formats.
|
6
|
+
#
|
7
|
+
module Parsers
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def format(format)
|
11
|
+
parsers[format]
|
12
|
+
end
|
13
|
+
|
14
|
+
def parsers
|
15
|
+
@parsers ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def register(format,parser)
|
19
|
+
parsers[format] = parser
|
20
|
+
end
|
21
|
+
|
22
|
+
def default=(parser)
|
23
|
+
parsers.default = parser
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'tmx/parsers/unknown'
|
29
|
+
require 'tmx/parsers/json'
|
30
|
+
require 'tmx/parsers/tmx'
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'zlib'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module Tmx
|
6
|
+
module Parser
|
7
|
+
|
8
|
+
#
|
9
|
+
# Parses the TMX formatted output from Tiled.
|
10
|
+
#
|
11
|
+
class Tmx
|
12
|
+
attr_reader :options
|
13
|
+
|
14
|
+
def initialize(options)
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse(contents)
|
19
|
+
results = Nokogiri::XML(contents)
|
20
|
+
convert_to_hash(results)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def convert_to_hash(xml)
|
26
|
+
{
|
27
|
+
"version" => map_attr(xml,"version").to_i,
|
28
|
+
"orientation" => map_attr(xml,"orientation"),
|
29
|
+
"width" => map_attr(xml,"width").to_i,
|
30
|
+
"height" => map_attr(xml,"height").to_i,
|
31
|
+
"tilewidth" => map_attr(xml,"tilewidth").to_i,
|
32
|
+
"tileheight" => map_attr(xml,"tileheight").to_i,
|
33
|
+
"properties" => properties(xml.xpath("/map")),
|
34
|
+
"layers" => map_layers(xml),
|
35
|
+
"tilesets" => map_tilesets(xml)
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def map_attr(xml,name)
|
40
|
+
xml.xpath("/map/@#{name}").text
|
41
|
+
end
|
42
|
+
|
43
|
+
def properties(xml)
|
44
|
+
properties = {}
|
45
|
+
xml.xpath("properties/property").each do |property|
|
46
|
+
properties[property.xpath("@name").text] = property.xpath("@value").text
|
47
|
+
end
|
48
|
+
properties
|
49
|
+
end
|
50
|
+
|
51
|
+
def layer_attr(layer,name,options)
|
52
|
+
layer.xpath("@#{name}").text == "" ? options[:default] : layer.xpath("@#{name}").text
|
53
|
+
end
|
54
|
+
|
55
|
+
def map_layers(xml)
|
56
|
+
layers = []
|
57
|
+
|
58
|
+
xml.xpath("/map/layer").each do |layer|
|
59
|
+
layer_hash = {}
|
60
|
+
|
61
|
+
layer_hash["name"] = layer.xpath("@name").text
|
62
|
+
layer_hash["width"] = layer.xpath("@width").text.to_i
|
63
|
+
layer_hash["height"] = layer.xpath("@height").text.to_i
|
64
|
+
|
65
|
+
layer_hash["type"] = layer_attr(layer,"type",default: "tilelayer")
|
66
|
+
layer_hash["opacity"] = layer_attr(layer,"opacity",default: 1.0).to_f
|
67
|
+
layer_hash["visible"] = (layer.xpath("@visible").text =~ /^false$/ ? false : true)
|
68
|
+
|
69
|
+
layer_hash["x"] = layer.xpath("@x").text.to_i
|
70
|
+
layer_hash["y"] = layer.xpath("@y").text.to_i
|
71
|
+
|
72
|
+
layer_hash["data"] = data_from_layer(layer)
|
73
|
+
|
74
|
+
layers.push layer_hash
|
75
|
+
end
|
76
|
+
layers
|
77
|
+
end
|
78
|
+
|
79
|
+
def data_from_layer(layer)
|
80
|
+
layer_data = layer.xpath("data").text.strip
|
81
|
+
|
82
|
+
if layer.xpath("data/@encoding").text == "base64"
|
83
|
+
layer_data = Base64.decode64(layer_data)
|
84
|
+
end
|
85
|
+
|
86
|
+
if layer.xpath("data/@compression").text == "zlib"
|
87
|
+
data = unpack_data zlib_decompress(layer_data)
|
88
|
+
elsif layer.xpath("data/@compression").text == "gzip"
|
89
|
+
data = unpack_data gzip_decompress(layer_data)
|
90
|
+
elsif layer.xpath("data/@encoding").text == "base64"
|
91
|
+
data = unpack_data(layer_data)
|
92
|
+
elsif layer.xpath("data/@encoding").text == "csv"
|
93
|
+
data = layer_data.split(",").map(&:to_i)
|
94
|
+
else
|
95
|
+
data = layer.xpath("data/tile").map { |tile| tile.xpath("@gid").text.to_i }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def zlib_decompress(data)
|
100
|
+
Zlib::Inflate.inflate(data)
|
101
|
+
end
|
102
|
+
|
103
|
+
def gzip_decompress(data)
|
104
|
+
Zlib::GzipReader.new(StringIO.new(data)).read
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Convert the XML data format into a valid format in Ruby.
|
109
|
+
#
|
110
|
+
# @see http://sourceforge.net/apps/mediawiki/tiled/index.php?title=Examining_the_map_format
|
111
|
+
# @see http://www.ruby-doc.org/core-2.0/String.html#method-i-unpack
|
112
|
+
#
|
113
|
+
# V | Integer | 32-bit unsigned, VAX (little-endian) byte order
|
114
|
+
#
|
115
|
+
def unpack_data(data)
|
116
|
+
data.unpack("V" * (data.length / 4))
|
117
|
+
end
|
118
|
+
|
119
|
+
def map_tilesets(xml)
|
120
|
+
xml.xpath("map/tileset").map do |tileset|
|
121
|
+
image = tileset.xpath("image")
|
122
|
+
|
123
|
+
properties = {
|
124
|
+
"firstgid" => tileset.xpath("@firstgid").text.to_i,
|
125
|
+
"name" => tileset.xpath("@name").text,
|
126
|
+
"tilewidth" => tileset.xpath("@tilewidth").text.to_i,
|
127
|
+
"tileheight" => tileset.xpath("@tileheight").text.to_i,
|
128
|
+
"spacing" => tileset.xpath("@spacing").text.to_i,
|
129
|
+
"margin" => tileset.xpath("@margin").text.to_i,
|
130
|
+
"image" => image.xpath("@source").text,
|
131
|
+
"imageheight" => image.xpath("@height").text.to_i,
|
132
|
+
"imagewidth" => image.xpath("@width").text.to_i,
|
133
|
+
"properties" => properties(xml)
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
Parsers.register :tmx, Parser::Tmx
|
145
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Tmx
|
2
|
+
module Parser
|
3
|
+
|
4
|
+
#
|
5
|
+
# The Unknown Parser is used to generate an error when the format
|
6
|
+
# is not supported or unknown.
|
7
|
+
#
|
8
|
+
class Unknown
|
9
|
+
attr_reader :options
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse(contents)
|
16
|
+
raise "Unknown Parser Type: Could not find an available parser for format #{options[:format]}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
Parsers.default = Parser::Unknown
|
23
|
+
|
24
|
+
end
|
data/lib/tmx/tile_set.rb
CHANGED
@@ -1,35 +1,5 @@
|
|
1
1
|
module Tmx
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
# end
|
7
|
-
#
|
8
|
-
# def load_tiles file_name_or_images, properties = {}
|
9
|
-
# properties = properties.dup
|
10
|
-
# first_id = properties.delete :firstgid
|
11
|
-
# tile_width = properties.delete :tilewidth
|
12
|
-
# tile_height = properties.delete :tileheight
|
13
|
-
#
|
14
|
-
# @tiles[first_id..-1] = case file_name_or_images
|
15
|
-
# when String then Gosu::Image.load_tiles(@map.window, file_name_or_images, tile_width, tile_height, true).freeze
|
16
|
-
# when Array then file_name_or_images.dup
|
17
|
-
# else raise ArgumentError, "must supply a file name or an array of images"
|
18
|
-
# end
|
19
|
-
#
|
20
|
-
# end # load_tiles
|
21
|
-
#
|
22
|
-
# def map; @map.__getobj__ end
|
23
|
-
#
|
24
|
-
# def [] tile_id
|
25
|
-
# raise IndexError unless (0...@tiles.length).include? tile_id
|
26
|
-
# @tiles[tile_id]
|
27
|
-
# end
|
28
|
-
#
|
29
|
-
# def []= tile_id, image
|
30
|
-
# raise IndexError unless (1...@tiles.length).include? tile_id
|
31
|
-
# @tiles[tile_id] = image
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# end
|
35
|
-
end
|
2
|
+
class TileSet < OpenStruct
|
3
|
+
|
4
|
+
end
|
5
|
+
end
|
data/lib/tmx/version.rb
CHANGED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Tmx, "JSON Format" do
|
4
|
+
|
5
|
+
let(:fixture_file) { File.join File.dirname(__FILE__), "..", "fixtures", "map.json" }
|
6
|
+
|
7
|
+
let(:map) do
|
8
|
+
described_class.load(fixture_file)
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:subject) { map }
|
12
|
+
|
13
|
+
its(:version) { should eq 1 }
|
14
|
+
|
15
|
+
its(:height) { should eq 12 }
|
16
|
+
its(:width) { should eq 16 }
|
17
|
+
|
18
|
+
its(:tileheight) { should eq 50 }
|
19
|
+
its(:tilewidth) { should eq 50 }
|
20
|
+
|
21
|
+
its(:orientation) { should eq "orthogonal" }
|
22
|
+
|
23
|
+
describe '#properties' do
|
24
|
+
it "has the correct number of properties" do
|
25
|
+
expect(subject.properties).to have(1).item
|
26
|
+
end
|
27
|
+
|
28
|
+
it "property values are correct" do
|
29
|
+
expect(subject.properties["hero.position"]).to eq "400,525,1"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#layers' do
|
34
|
+
it "has the correct number of layers" do
|
35
|
+
expect(subject.layers).to have(1).item
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when evaluating the first layer" do
|
39
|
+
|
40
|
+
let(:subject) { map.layers.first }
|
41
|
+
|
42
|
+
its(:name) { should eq "Tile Layer 1" }
|
43
|
+
its(:opacity) { should eq 1 }
|
44
|
+
its(:type) { should eq "tilelayer" }
|
45
|
+
its(:visible) { should be_true }
|
46
|
+
its(:height) { should eq 12 }
|
47
|
+
its(:width) { should eq 16 }
|
48
|
+
its(:x) { should eq 0 }
|
49
|
+
its(:y) { should eq 0 }
|
50
|
+
|
51
|
+
its(:data) { should eq [ 3, 3, 3, 3, 3, 3, 2, 5, 5, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 7, 18, 9, 9, 17, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 15, 14, 4, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 4, 4, 4, 6, 7, 3, 3, 3, 3, 3, 18, 9, 17, 2, 4, 4, 10, 13, 4, 10, 11, 3, 3, 3, 3, 18, 14, 6, 7, 2, 4, 4, 7, 16, 8, 11, 3, 3, 3, 3, 3, 2, 4, 4, 15, 14, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 4, 4, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 16, 8, 8, 8, 13, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 12, 12, 12, 12, 16, 8, 8, 11, 3, 3, 3, 3, 3, 3] }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#tilesets' do
|
56
|
+
it "has the correct number of tilesets" do
|
57
|
+
expect(subject.tilesets).to have(1).item
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when evaluating the first tileset" do
|
61
|
+
let(:subject) { map.tilesets.first }
|
62
|
+
|
63
|
+
its(:firstgid) { should eq 1 }
|
64
|
+
its(:image) { should eq "tiles.png" }
|
65
|
+
its(:imageheight) { should eq 250 }
|
66
|
+
its(:imagewidth) { should eq 200 }
|
67
|
+
its(:margin) { should eq 0 }
|
68
|
+
its(:name) { should eq "tiles" }
|
69
|
+
its(:spacing) { should eq 0 }
|
70
|
+
its(:tileheight) { should eq 50 }
|
71
|
+
its(:tilewidth) { should eq 50 }
|
72
|
+
its(:properties) { should eq({}) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Tmx, "TMX Formats" do
|
4
|
+
|
5
|
+
[ :zlib, :gzip, :uncompressed, :csv, :xml ].each do |format|
|
6
|
+
|
7
|
+
describe "#{format}" do
|
8
|
+
|
9
|
+
let(:fixture_file) { File.join File.dirname(__FILE__), "..", "fixtures", "map_#{format}.tmx" }
|
10
|
+
|
11
|
+
let(:map) do
|
12
|
+
described_class.load(fixture_file)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:subject) { map }
|
16
|
+
|
17
|
+
its(:version) { should eq 1 }
|
18
|
+
|
19
|
+
its(:height) { should eq 12 }
|
20
|
+
its(:width) { should eq 16 }
|
21
|
+
|
22
|
+
its(:tileheight) { should eq 50 }
|
23
|
+
its(:tilewidth) { should eq 50 }
|
24
|
+
|
25
|
+
its(:orientation) { should eq "orthogonal" }
|
26
|
+
|
27
|
+
describe '#properties' do
|
28
|
+
it "has the correct number of properties" do
|
29
|
+
expect(subject.properties).to have(1).item
|
30
|
+
end
|
31
|
+
|
32
|
+
it "property values are correct" do
|
33
|
+
expect(subject.properties["hero.position"]).to eq "400,525,1"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#layers' do
|
38
|
+
it "has the correct number of layers" do
|
39
|
+
expect(subject.layers).to have(1).item
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when evaluating the first layer" do
|
43
|
+
|
44
|
+
let(:subject) { map.layers.first }
|
45
|
+
|
46
|
+
its(:name) { should eq "Tile Layer 1" }
|
47
|
+
its(:opacity) { should eq 1 }
|
48
|
+
its(:type) { should eq "tilelayer" }
|
49
|
+
its(:visible) { should be_true }
|
50
|
+
its(:height) { should eq 12 }
|
51
|
+
its(:width) { should eq 16 }
|
52
|
+
its(:x) { should eq 0 }
|
53
|
+
its(:y) { should eq 0 }
|
54
|
+
|
55
|
+
its(:data) { should eq [ 3, 3, 3, 3, 3, 3, 2, 5, 5, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 7, 18, 9, 9, 17, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 15, 14, 4, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 4, 4, 4, 6, 7, 3, 3, 3, 3, 3, 18, 9, 17, 2, 4, 4, 10, 13, 4, 10, 11, 3, 3, 3, 3, 18, 14, 6, 7, 2, 4, 4, 7, 16, 8, 11, 3, 3, 3, 3, 3, 2, 4, 4, 15, 14, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 4, 4, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 16, 8, 8, 8, 13, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 12, 12, 12, 12, 16, 8, 8, 11, 3, 3, 3, 3, 3, 3] }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#tilesets' do
|
60
|
+
it "has the correct number of tilesets" do
|
61
|
+
expect(subject.tilesets).to have(1).item
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when evaluating the first tileset" do
|
65
|
+
let(:subject) { map.tilesets.first }
|
66
|
+
|
67
|
+
its(:firstgid) { should eq 1 }
|
68
|
+
its(:image) { should eq "tiles.png" }
|
69
|
+
its(:imageheight) { should eq 250 }
|
70
|
+
its(:imagewidth) { should eq 200 }
|
71
|
+
its(:margin) { should eq 0 }
|
72
|
+
its(:name) { should eq "tiles" }
|
73
|
+
its(:spacing) { should eq 0 }
|
74
|
+
its(:tileheight) { should eq 50 }
|
75
|
+
its(:tilewidth) { should eq 50 }
|
76
|
+
its(:properties) { should eq({}) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
{ "height":12,
|
2
|
+
"layers":[
|
3
|
+
{
|
4
|
+
"data":[3, 3, 3, 3, 3, 3, 2, 5, 5, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 7, 18, 9, 9, 17, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 15, 14, 4, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 4, 4, 4, 6, 7, 3, 3, 3, 3, 3, 18, 9, 17, 2, 4, 4, 10, 13, 4, 10, 11, 3, 3, 3, 3, 18, 14, 6, 7, 2, 4, 4, 7, 16, 8, 11, 3, 3, 3, 3, 3, 2, 4, 4, 15, 14, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 2, 4, 4, 4, 4, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 16, 8, 8, 8, 13, 4, 4, 7, 3, 3, 3, 3, 3, 3, 3, 3, 12, 12, 12, 12, 16, 8, 8, 11, 3, 3, 3, 3, 3, 3],
|
5
|
+
"height":12,
|
6
|
+
"name":"Tile Layer 1",
|
7
|
+
"opacity":1,
|
8
|
+
"type":"tilelayer",
|
9
|
+
"visible":true,
|
10
|
+
"width":16,
|
11
|
+
"x":0,
|
12
|
+
"y":0
|
13
|
+
}],
|
14
|
+
"orientation":"orthogonal",
|
15
|
+
"properties":
|
16
|
+
{
|
17
|
+
"hero.position":"400,525,1"
|
18
|
+
},
|
19
|
+
"tileheight":50,
|
20
|
+
"tilesets":[
|
21
|
+
{
|
22
|
+
"firstgid":1,
|
23
|
+
"image":"tiles.png",
|
24
|
+
"imageheight":250,
|
25
|
+
"imagewidth":200,
|
26
|
+
"margin":0,
|
27
|
+
"name":"tiles",
|
28
|
+
"properties":
|
29
|
+
{
|
30
|
+
|
31
|
+
},
|
32
|
+
"spacing":0,
|
33
|
+
"tileheight":50,
|
34
|
+
"tilewidth":50
|
35
|
+
}],
|
36
|
+
"tilewidth":50,
|
37
|
+
"version":1,
|
38
|
+
"width":16
|
39
|
+
}
|