tmx 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +1 -1
- data/Rakefile +1 -0
- data/lib/tmx/image_layer.rb +5 -0
- data/lib/tmx/map.rb +11 -0
- data/lib/tmx/object.rb +5 -0
- data/lib/tmx/object_group.rb +9 -0
- data/lib/tmx/parsers/json.rb +49 -1
- data/lib/tmx/parsers/tmx.rb +59 -1
- data/lib/tmx/version.rb +1 -1
- data/spec/features/json_format_spec.rb +119 -11
- data/spec/features/json_isometric_format_spec.rb +76 -0
- data/spec/features/xml_format_spec.rb +128 -21
- data/spec/fixtures/map-isometric.json +50 -0
- data/spec/fixtures/map.json +153 -11
- data/spec/fixtures/map_csv.tmx +36 -18
- data/spec/fixtures/map_gzip.tmx +35 -6
- data/spec/fixtures/map_uncompressed.tmx +35 -6
- data/spec/fixtures/map_xml.tmx +35 -197
- data/spec/fixtures/map_zlib.tmx +31 -5
- data/spec/fixtures/tiles.png +0 -0
- data/tmx.gemspec +1 -1
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OTA3ZjIyZjNjZGZhYTg0ZGVjNWY0NjkyZDQ2MjcwYTM2YmRkZmY3NA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ODA2YWY5OTJjN2FiMzFlOTYyN2M3YWIwODgxY2Q5ODc4MjQ2ZDRlNQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MjBlM2NhZTU3OTZjYzZkZjcyMjU4ZmVhNjIyNDE1ZjFlMjY1OTgwMzIwMzFk
|
10
|
+
Y2NjYTE1Mjg4NGMzNjZiYzc5OTc5M2M0M2Y5ZDM1NGRhYWRiNzg3ODQ3ZjQ0
|
11
|
+
YTc0NmQzNjU5NDU4ZDI5NTNlYTkwZTViZjMzOTFhNTQ2ZGM4ZjY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ODIyZGIzNmJkOTI2NzExZTc0YzA3YmJjMzdiNzY3YjA5NzM2NTExMTliMzIw
|
14
|
+
NGRmN2M0ZDgyMTg4Yzk0YTc4ZGMxY2Q5OWY3MTMwOThiNDkyOTIwOThhYTlm
|
15
|
+
OTQ1MzQ2ZWRlNzE3MmQyYzkyM2RmOTI3NDRmNzk3YTlmYjAzMDI=
|
data/README.md
CHANGED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/tmx/map.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'tmx/tile_set'
|
2
2
|
require 'tmx/layer'
|
3
|
+
require 'tmx/object_group'
|
4
|
+
require 'tmx/object'
|
5
|
+
require 'tmx/image_layer'
|
3
6
|
|
4
7
|
module Tmx
|
5
8
|
|
@@ -11,5 +14,13 @@ module Tmx
|
|
11
14
|
def tilesets
|
12
15
|
@tilesets ||= Array(contents['tilesets']).map {|set| TileSet.new set.merge(contents: set) }
|
13
16
|
end
|
17
|
+
|
18
|
+
def object_groups
|
19
|
+
@object_groups ||= Array(contents['object_groups']).map {|group| ObjectGroup.new group.merge(contents: group) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def image_layers
|
23
|
+
@object_groups ||= Array(contents['image_layers']).map {|layer| ImageLayer.new layer.merge(contents: layer) }
|
24
|
+
end
|
14
25
|
end
|
15
26
|
end
|
data/lib/tmx/object.rb
ADDED
data/lib/tmx/parsers/json.rb
CHANGED
@@ -14,8 +14,56 @@ module Tmx
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def parse(contents)
|
17
|
-
Oj.load(contents)
|
17
|
+
parsed_contents = Oj.load(contents)
|
18
|
+
|
19
|
+
object_layers = parsed_contents["layers"].find_all do |layer|
|
20
|
+
layer["type"] == "objectgroup"
|
21
|
+
end
|
22
|
+
|
23
|
+
parsed_contents["object_groups"] = object_layers
|
24
|
+
|
25
|
+
object_layers.each do |object_layer|
|
26
|
+
parse_object_layer(object_layer)
|
27
|
+
end
|
28
|
+
|
29
|
+
image_layers = parsed_contents["layers"].find_all do |layer|
|
30
|
+
layer["type"] == "imagelayer"
|
31
|
+
end
|
32
|
+
|
33
|
+
parsed_contents["image_layers"] = image_layers
|
34
|
+
|
35
|
+
parsed_contents["layers"].reject! {|layer| layer["type"] != "tilelayer" }
|
36
|
+
|
37
|
+
parsed_contents
|
38
|
+
|
18
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def parse_object_layer(object_layer)
|
44
|
+
object_layer["objects"].each do |object|
|
45
|
+
|
46
|
+
if object["ellipse"]
|
47
|
+
object["shape"] = "ellipse"
|
48
|
+
elsif object["polyline"]
|
49
|
+
object["shape"] = "polyline"
|
50
|
+
object["points"] = object["polyline"].map {|h| "#{h["x"]},#{h["y"]}" }
|
51
|
+
elsif object["polygon"]
|
52
|
+
object["shape"] = "polygon"
|
53
|
+
object["points"] = object["polygon"].map {|h| "#{h["x"]},#{h["y"]}" }
|
54
|
+
else
|
55
|
+
x = object["x"]
|
56
|
+
y = object["y"]
|
57
|
+
width = object["width"]
|
58
|
+
height = object["height"]
|
59
|
+
|
60
|
+
object["shape"] = "polygon"
|
61
|
+
object["points"] = [ "#{x},#{y}", "#{x + width},#{y}", "#{x + width},#{y + height}", "#{x},#{y + height}" ]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
19
67
|
end
|
20
68
|
|
21
69
|
end
|
data/lib/tmx/parsers/tmx.rb
CHANGED
@@ -32,7 +32,9 @@ module Tmx
|
|
32
32
|
"tileheight" => map_attr(xml,"tileheight").to_i,
|
33
33
|
"properties" => properties(xml.xpath("/map")),
|
34
34
|
"layers" => map_layers(xml),
|
35
|
-
"tilesets" => map_tilesets(xml)
|
35
|
+
"tilesets" => map_tilesets(xml),
|
36
|
+
"object_groups" => map_object_groups(xml),
|
37
|
+
"image_layers" => map_image_layers(xml)
|
36
38
|
}
|
37
39
|
end
|
38
40
|
|
@@ -133,8 +135,64 @@ module Tmx
|
|
133
135
|
"properties" => properties(xml)
|
134
136
|
}
|
135
137
|
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def map_object_groups(xml)
|
141
|
+
xml.xpath("map/objectgroup").map do |object_group|
|
142
|
+
|
143
|
+
objects = object_group.xpath("object").map do |object|
|
144
|
+
properties = {
|
145
|
+
"name" => object.xpath("@name").text,
|
146
|
+
"type" => object.xpath("@type").text,
|
147
|
+
"x" => object.xpath("@x").text.to_i,
|
148
|
+
"y" => object.xpath("@y").text.to_i,
|
149
|
+
"width" => object.xpath("@width").text.to_i,
|
150
|
+
"height" => object.xpath("@height").text.to_i,
|
151
|
+
"visible" => (object.xpath("@visible").text =~ /^false$/ ? false : true),
|
152
|
+
"properties" => properties(object)
|
153
|
+
}
|
154
|
+
|
155
|
+
properties.merge(object_shape(object))
|
156
|
+
end
|
157
|
+
|
158
|
+
{
|
159
|
+
"name" => object_group.xpath("@name").text,
|
160
|
+
"width" => object_group.xpath("@width").text.to_i,
|
161
|
+
"height" => object_group.xpath("@height").text.to_i,
|
162
|
+
"opacity" => (object_group.xpath("@opacity").text == "" ? 1.0 : object_group.xpath("@opacity").text.to_f),
|
163
|
+
"objects" => objects
|
164
|
+
}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def object_shape(object)
|
169
|
+
if not object.xpath("ellipse").empty?
|
170
|
+
{ "shape" => "ellipse" }
|
171
|
+
elsif not object.xpath("polyline").empty?
|
172
|
+
points = object.xpath("polyline/@points").text.split(" ")
|
173
|
+
{ "shape" => "polyline", "points" => points }
|
174
|
+
elsif not object.xpath("polygon").empty?
|
175
|
+
points = object.xpath("polygon/@points").text.split(" ")
|
176
|
+
{ "shape" => "polygon", "points" => points }
|
177
|
+
else
|
178
|
+
x = object.xpath("@x").text.to_i
|
179
|
+
y = object.xpath("@y").text.to_i
|
180
|
+
width = object.xpath("@width").text.to_i
|
181
|
+
height = object.xpath("@height").text.to_i
|
182
|
+
{ "shape" => "polygon", "points" => [ "#{x},#{y}", "#{x + width},#{y}", "#{x + width},#{y + height}", "#{x},#{y + height}" ] }
|
183
|
+
end
|
184
|
+
end
|
136
185
|
|
186
|
+
def map_image_layers(xml)
|
187
|
+
xml.xpath("map/imagelayer").map do |image_layer|
|
137
188
|
|
189
|
+
{
|
190
|
+
"name" => image_layer.xpath("@name").text,
|
191
|
+
"width" => image_layer.xpath("@width").text.to_i,
|
192
|
+
"height" => image_layer.xpath("@height").text.to_i
|
193
|
+
}
|
194
|
+
|
195
|
+
end
|
138
196
|
end
|
139
197
|
|
140
198
|
end
|
data/lib/tmx/version.rb
CHANGED
@@ -15,8 +15,8 @@ describe Tmx, "JSON Format" do
|
|
15
15
|
its(:height) { should eq 12 }
|
16
16
|
its(:width) { should eq 16 }
|
17
17
|
|
18
|
-
its(:tileheight) { should eq
|
19
|
-
its(:tilewidth) { should eq
|
18
|
+
its(:tileheight) { should eq 32 }
|
19
|
+
its(:tilewidth) { should eq 32 }
|
20
20
|
|
21
21
|
its(:orientation) { should eq "orthogonal" }
|
22
22
|
|
@@ -39,7 +39,7 @@ describe Tmx, "JSON Format" do
|
|
39
39
|
|
40
40
|
let(:subject) { map.layers.first }
|
41
41
|
|
42
|
-
its(:name) { should eq "
|
42
|
+
its(:name) { should eq "Layer" }
|
43
43
|
its(:opacity) { should eq 1 }
|
44
44
|
its(:type) { should eq "tilelayer" }
|
45
45
|
its(:visible) { should be_true }
|
@@ -48,7 +48,7 @@ describe Tmx, "JSON Format" do
|
|
48
48
|
its(:x) { should eq 0 }
|
49
49
|
its(:y) { should eq 0 }
|
50
50
|
|
51
|
-
its(:data) { should eq [
|
51
|
+
its(:data) { should eq [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 142, 20, 0, 0, 0, 141, 142, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 30, 0, 0, 0, 0, 0, 25, 26, 27, 0, 0, 0, 0, 0, 46, 47, 48, 0, 0, 0, 0, 0, 43, 44, 45, 0, 0, 0, 0, 0, 0, 65, 0, 0, 8, 8, 8, 23, 0, 80, 0, 137, 138, 0, 0, 0, 0, 83, 0, 0, 0, 0, 50, 0, 0, 80, 0, 191, 192, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 19, 37, 38, 37, 37, 37, 38, 37, 37, 37, 37, 37, 19, 37, 37, 37, 37, 37, 37, 37, 37] }
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -62,14 +62,122 @@ describe Tmx, "JSON Format" do
|
|
62
62
|
|
63
63
|
its(:firstgid) { should eq 1 }
|
64
64
|
its(:image) { should eq "tiles.png" }
|
65
|
-
its(:imageheight) { should eq
|
66
|
-
its(:imagewidth) { should eq
|
67
|
-
its(:margin) { should eq
|
65
|
+
its(:imageheight) { should eq 400 }
|
66
|
+
its(:imagewidth) { should eq 640 }
|
67
|
+
its(:margin) { should eq 2 }
|
68
68
|
its(:name) { should eq "tiles" }
|
69
|
-
its(:spacing) { should eq
|
70
|
-
its(:tileheight) { should eq
|
71
|
-
its(:tilewidth) { should eq
|
72
|
-
its(:properties) { should eq({}) }
|
69
|
+
its(:spacing) { should eq 2 }
|
70
|
+
its(:tileheight) { should eq 32 }
|
71
|
+
its(:tilewidth) { should eq 32 }
|
72
|
+
its(:properties) { should eq({ "alpha" => "1" }) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '#object_groups' do
|
77
|
+
it "has the correct number of object groups" do
|
78
|
+
expect(subject.object_groups).to have(1).item
|
79
|
+
end
|
80
|
+
|
81
|
+
context "when evaluating the first object group" do
|
82
|
+
|
83
|
+
let(:subject) { map.object_groups.first }
|
84
|
+
|
85
|
+
its(:name) { should eq "Objects" }
|
86
|
+
its(:width) { should eq 16 }
|
87
|
+
its(:height) { should eq 12 }
|
88
|
+
its(:objects) { should have(6).items }
|
89
|
+
its(:opacity) { should eq 1 }
|
90
|
+
|
91
|
+
context "when evaluating a rectangluar object" do
|
92
|
+
let(:subject) { map.object_groups.first.objects.first }
|
93
|
+
|
94
|
+
its(:name) { should eq "ground" }
|
95
|
+
its(:type) { should eq "floor" }
|
96
|
+
its(:x) { should eq 0 }
|
97
|
+
its(:y) { should eq 256 }
|
98
|
+
its(:width) { should eq 512 }
|
99
|
+
its(:height) { should eq 32 }
|
100
|
+
its(:visible) { should be_true }
|
101
|
+
|
102
|
+
its(:properties) { should have(1).item }
|
103
|
+
|
104
|
+
its(:shape) { should eq "polygon" }
|
105
|
+
its(:points) { should eq [ "0,256", "512,256", "512,288", "0,288" ]}
|
106
|
+
|
107
|
+
it "has the correct properties" do
|
108
|
+
expect(subject.properties["type"]).to eq "sand"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when evaluating a circular object" do
|
113
|
+
|
114
|
+
let(:subject) { map.object_groups.first.objects[2] }
|
115
|
+
|
116
|
+
its(:name) { should eq "mushroom" }
|
117
|
+
its(:type) { should eq "mushroom" }
|
118
|
+
its(:x) { should eq 256 }
|
119
|
+
its(:y) { should eq 224 }
|
120
|
+
its(:width) { should eq 32 }
|
121
|
+
its(:height) { should eq 32 }
|
122
|
+
its(:visible) { should be_true }
|
123
|
+
|
124
|
+
its(:properties) { should have(1).item }
|
125
|
+
|
126
|
+
its(:shape) { should eq "ellipse" }
|
127
|
+
|
128
|
+
it "has the correct properties" do
|
129
|
+
expect(subject.properties["player.life.bonus"]).to eq "1"
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
context "when evaluating a polygon (triangle)" do
|
135
|
+
|
136
|
+
let(:subject) { map.object_groups.first.objects[3] }
|
137
|
+
|
138
|
+
its(:name) { should eq "danger" }
|
139
|
+
its(:type) { should eq "sign" }
|
140
|
+
its(:x) { should eq 448 }
|
141
|
+
its(:y) { should eq 192 }
|
142
|
+
its(:shape) { should eq "polygon" }
|
143
|
+
its(:points) { should eq [ "0,0", "32,64", "-32,64", "0,0"] }
|
144
|
+
its(:visible) { should be_true }
|
145
|
+
|
146
|
+
its(:properties) { should have(0).items }
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
context "when evaluating a polyline (line segments)" do
|
151
|
+
|
152
|
+
let(:subject) { map.object_groups.first.objects[4] }
|
153
|
+
|
154
|
+
its(:name) { should eq "dirt" }
|
155
|
+
its(:type) { should eq "underground" }
|
156
|
+
its(:x) { should eq 32 }
|
157
|
+
its(:y) { should eq 320 }
|
158
|
+
its(:visible) { should be_true }
|
159
|
+
|
160
|
+
its(:properties) { should have(3).items }
|
161
|
+
|
162
|
+
its(:shape) { should eq "polyline" }
|
163
|
+
its(:points) { should eq ["0,0", "448,0", "448,64", "0,64", "0,0"]}
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
describe '#image_layers' do
|
171
|
+
it "has the correct number of image layers" do
|
172
|
+
expect(subject.image_layers).to have(1).item
|
173
|
+
end
|
174
|
+
|
175
|
+
context "when evaluating the first image layer" do
|
176
|
+
let(:subject) { map.image_layers.first }
|
177
|
+
|
178
|
+
its(:name) { should eq "Image Layer" }
|
179
|
+
its(:width) { should eq 16 }
|
180
|
+
its(:height) { should eq 12 }
|
73
181
|
end
|
74
182
|
end
|
75
183
|
|
@@ -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-isometric.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
|