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
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OGY5ZWFiM2U3NWQ1M2NjYzUxYzI3ODkxNTMyMTllZWFmZDA1YzM1Nw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZGZhODNjYzFjYWMzMjc5ZmZlZGMxNWVjODY4MGUzODYzZmNhZjRmYw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MjZjZDljYzVmZmM5ODJjNGYzNzRiNmEyMzZiYzcxOTRhZmZjODI0MjQ0MjA1
|
10
|
+
ZmYxMmNmOTA1Zjc5MmI1NGEzYWFjNWUxYTdjMjhiZTViYzg2Y2QyNzAyMjRh
|
11
|
+
OTUwZDk3NmQwOTViYWRlZjk2OWQwZWVhNjRlNzZhODA5OGJhYzk=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MWU1Y2QxMzEyOWY5MDJjOWUzMjU5NjcyZDY0ZWRmZWYxODNmNzU2MjczZTc1
|
14
|
+
N2QxNjQyZmU1MGZjNTQzZmVkY2I1NWI4MzBjNmY5NzkyMTQ0OWRlNWJkZTY3
|
15
|
+
MWZjMjRiM2MwMzFhOTkyNTNhMzI5YWNmNjM5NmIxZTAwZjNhNWM=
|
data/.gitignore
CHANGED
@@ -1,12 +1,17 @@
|
|
1
|
-
|
2
|
-
*.
|
3
|
-
|
4
|
-
|
5
|
-
coverage
|
6
|
-
.DS_Store
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
7
5
|
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
8
17
|
tmp
|
9
|
-
tags
|
10
|
-
ctags
|
11
|
-
.bundle
|
12
|
-
*.lock
|
data/.rspec
ADDED
data/Gemfile
CHANGED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Shawn Anderson, Franklin Webber
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Tmx
|
2
|
+
|
3
|
+
A library for parsing the **[Tiled Map Editor](http://www.mapeditor.org/)** file format.
|
4
|
+
|
5
|
+
## Support
|
6
|
+
|
7
|
+
* JSON format
|
8
|
+
* TMX file (XML)
|
9
|
+
* TMX file (Base64)
|
10
|
+
* TMX file (Base64 zlib compressed)
|
11
|
+
* TMX file (Base64 gzip compressed)
|
12
|
+
* TMX file (CSV)
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'tmx'
|
20
|
+
```
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
```bash
|
25
|
+
$ bundle
|
26
|
+
```
|
27
|
+
|
28
|
+
Or install it yourself as:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
$ gem install tmx
|
32
|
+
```
|
data/lib/tmx.rb
CHANGED
@@ -1,16 +1,55 @@
|
|
1
|
-
|
2
|
-
autoload :Nokogiri, 'nokogiri'
|
3
|
-
autoload :WeakRef, 'weakref'
|
4
|
-
# autoload :Zlib, 'zlib'
|
1
|
+
require 'ostruct'
|
5
2
|
|
6
|
-
|
7
|
-
require
|
8
|
-
|
9
|
-
require 'tmx/nokogiri_additions'
|
3
|
+
require "tmx/version"
|
4
|
+
require "tmx/parsers/parsers"
|
5
|
+
require "tmx/map"
|
10
6
|
|
11
7
|
module Tmx
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
extend self
|
9
|
+
|
10
|
+
#
|
11
|
+
# Load the specified TMX file and return a Map that was found.
|
12
|
+
#
|
13
|
+
# @param [String] filename the name fo the Tiled Map file.
|
14
|
+
# @param [Hash] options
|
15
|
+
#
|
16
|
+
# @returns [Map] the map instance defined within the specified file
|
17
|
+
#
|
18
|
+
def load(filename,options={})
|
19
|
+
options = default_options(filename).merge(options)
|
20
|
+
parse contents(filename), options
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Parse the the string contents of a TMX file.
|
25
|
+
#
|
26
|
+
# @returns [Map] the map instance defined within the string
|
27
|
+
def parse(contents,options={})
|
28
|
+
contents = parser(options).parse contents
|
29
|
+
Map.new contents.merge(contents: contents)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def format(filename)
|
35
|
+
File.extname(filename)[1..-1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def contents(filename)
|
39
|
+
File.read(filename)
|
40
|
+
end
|
41
|
+
|
42
|
+
def default_options(filename)
|
43
|
+
{ format: format(filename) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def parser(options)
|
47
|
+
format = options[:format].to_sym
|
48
|
+
parsers[format].new(options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def parsers
|
52
|
+
Parsers.parsers
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
data/lib/tmx/layer.rb
CHANGED
@@ -1,74 +1,5 @@
|
|
1
1
|
module Tmx
|
2
|
-
class Layer
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
def initialize map, data, properties
|
7
|
-
@map = WeakRef.new map
|
8
|
-
@properties = properties.dup
|
9
|
-
|
10
|
-
@columns = @properties.delete(:width) or raise ArgumentError, "layer width is required"
|
11
|
-
@rows = @properties.delete(:height) or raise ArgumentError, "layer height is required"
|
12
|
-
|
13
|
-
@tile_ids = case data
|
14
|
-
when String then data.unpack('V*')
|
15
|
-
when Array then data.dup
|
16
|
-
when nil then Array.new @columns * @rows, 0
|
17
|
-
else raise ArgumentError, "data must be a binary string or an array of integers"
|
18
|
-
end
|
19
|
-
end # initialize
|
20
|
-
|
21
|
-
def map; @map.__getobj__ end
|
22
|
-
|
23
|
-
def [] x, y
|
24
|
-
raise IndexError unless x_range.include? x and y_range.include? y
|
25
|
-
@tile_ids[offset(x, y)]
|
26
|
-
end
|
27
|
-
|
28
|
-
def []= x, y, id
|
29
|
-
raise IndexError unless x_range.include? x and y_range.include? y
|
30
|
-
@tile_ids[offset(x, y)] = id
|
31
|
-
end
|
32
|
-
|
33
|
-
def each_tile_id &block
|
34
|
-
y_range.each do |y|
|
35
|
-
x_range.each do |x|
|
36
|
-
yield x, y, @tile_ids[offset(x, y)]
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end # each_tile_id
|
40
|
-
|
41
|
-
def x_range; 0...@columns end
|
42
|
-
def y_range; 0...@rows end
|
43
|
-
|
44
|
-
# def draw x_off, y_off, z_off, x_range, y_range
|
45
|
-
# x_range = [x_range.min, 0].max .. [x_range.max, @columns - 1].min
|
46
|
-
# y_range = [y_range.min, 0].max .. [y_range.max, @rows - 1].min
|
47
|
-
#
|
48
|
-
# tile_set = @map.tile_set
|
49
|
-
# tile_width = @map.tile_width
|
50
|
-
# tile_height = @map.tile_height
|
51
|
-
#
|
52
|
-
# y_range.each do |y|
|
53
|
-
# tile_y_off = y_off + y * tile_height
|
54
|
-
#
|
55
|
-
# x_range.each do |x|
|
56
|
-
# tile_x_off = x_off + x * tile_width
|
57
|
-
# tile_index = @tile_ids[offset(x, y)]
|
58
|
-
#
|
59
|
-
# image = tile_set[tile_index]
|
60
|
-
# next if image.nil?
|
61
|
-
#
|
62
|
-
# image.draw tile_x_off, tile_y_off, z_off, 1, 1, @color
|
63
|
-
# end
|
64
|
-
# end
|
65
|
-
# end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def offset x, y
|
70
|
-
x + y * @columns
|
71
|
-
end
|
72
|
-
|
73
|
-
end # Layer
|
74
|
-
end
|
2
|
+
class Layer < OpenStruct
|
3
|
+
|
4
|
+
end
|
5
|
+
end
|
data/lib/tmx/map.rb
CHANGED
@@ -1,147 +1,15 @@
|
|
1
|
+
require 'tmx/tile_set'
|
2
|
+
require 'tmx/layer'
|
3
|
+
|
1
4
|
module Tmx
|
2
|
-
class Map
|
3
|
-
# autoload :TileCache, 'tmx/map/tile_cache'
|
4
|
-
autoload :XMLLoader, 'tmx/map/xml_loader'
|
5
|
-
|
6
|
-
include XMLLoader
|
7
|
-
|
8
|
-
attr_reader :properties
|
9
|
-
attr_reader :columns, :rows
|
10
|
-
attr_reader :width, :height
|
11
|
-
attr_reader :tile_width, :tile_height
|
12
|
-
|
13
|
-
attr_reader :layers, :object_groups#, :tile_set
|
14
|
-
|
15
|
-
DEFAULT_OPTIONS = {
|
16
|
-
# Scales pixel units to tile units (if true) or user-defined scale (if
|
17
|
-
# numeric) when passing them to callbacks.
|
18
|
-
:scale_units => false,
|
19
|
-
|
20
|
-
# Hooks for object, layer and tile set creation. Only on_object is
|
21
|
-
# implemented so far.
|
22
|
-
:on_tile_set => nil,
|
23
|
-
:on_layer => nil,
|
24
|
-
:on_object => nil,
|
25
|
-
|
26
|
-
# This option discards all layer, object group and tile set info after
|
27
|
-
# building the tile cache; uses less memory if you don't intend to
|
28
|
-
# modify the map at run time.
|
29
|
-
:discard_structure => false,
|
30
|
-
|
31
|
-
# These three options allow finer grained control of what to throw away
|
32
|
-
# in case you intend to modify only certain aspects of the map.
|
33
|
-
:discard_layer_info => false,
|
34
|
-
:discard_object_info => false,
|
35
|
-
}
|
36
|
-
|
37
|
-
def initialize file_name, options = {}
|
38
|
-
options = DEFAULT_OPTIONS.merge options
|
39
|
-
|
40
|
-
# TODO move this XML code to an external module
|
41
|
-
# TODO allow file name or xml document?
|
42
|
-
# TODO allow other map formats?
|
43
|
-
|
44
|
-
mapdef = File.open(file_name) do |io|
|
45
|
-
doc = Nokogiri::XML(io) { |conf| conf.noent.noblanks }
|
46
|
-
|
47
|
-
# TODO figure out why this always fails
|
48
|
-
# errors = doc.validate
|
49
|
-
|
50
|
-
doc.root
|
51
|
-
end
|
52
|
-
|
53
|
-
# TODO proper version check; learn about Tmx versions if there are any
|
54
|
-
raise "Only version 1.0 maps are currently supported" unless mapdef['version'] == '1.0'
|
55
|
-
raise "Only orthogonal maps are currently supported" unless mapdef['orientation'] == 'orthogonal'
|
56
|
-
|
57
|
-
# @cache = TileCache.new self
|
58
|
-
|
59
|
-
@tile_width = mapdef['tilewidth'].to_i
|
60
|
-
@tile_height = mapdef['tileheight'].to_i
|
61
|
-
|
62
|
-
@columns = mapdef['width'].to_i
|
63
|
-
@rows = mapdef['height'].to_i
|
64
|
-
|
65
|
-
@scale_units = case options[:scale_units]
|
66
|
-
when Numeric then options[:scale_units].to_f
|
67
|
-
when :tile_width then 1.0 / @tile_width
|
68
|
-
when :tile_height then 1.0 / @tile_height
|
69
|
-
when true then 1.0 / [@tile_width, @tile_height].min
|
70
|
-
else false
|
71
|
-
end
|
72
|
-
|
73
|
-
if @scale_units
|
74
|
-
@width = @columns.to_f * @scale_units
|
75
|
-
@height = @rows.to_f * @scale_units
|
76
|
-
else
|
77
|
-
@width = @columns * @tile_width
|
78
|
-
@height = @rows * @tile_height
|
79
|
-
end
|
80
|
-
|
81
|
-
@properties = mapdef.tmx_parse_properties
|
82
|
-
|
83
|
-
# @tile_set = TileSet.new self
|
84
|
-
|
85
|
-
@layers = Hash[]
|
86
|
-
@object_groups = Hash[]
|
87
|
-
|
88
|
-
# callback for custom object creation
|
89
|
-
@on_object = options[:on_object]
|
90
|
-
|
91
|
-
# mapdef.xpath('tileset').each do |xml|
|
92
|
-
# @tile_set.load_tiles *parse_tile_set_def(xml)
|
93
|
-
# end
|
94
|
-
|
95
|
-
mapdef.xpath('layer').each do |xml|
|
96
|
-
layer = parse_layer_def xml
|
97
|
-
name = layer.properties[:name]
|
98
|
-
@layers[name] = layer
|
99
|
-
end # layers
|
100
|
-
|
101
5
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
@object_groups[name] = group
|
106
|
-
end # object groups
|
107
|
-
|
108
|
-
# @cache.rebuild!
|
109
|
-
|
110
|
-
discard_structure = @properties.delete(:discard_structure)
|
111
|
-
|
112
|
-
@layers = nil if @properties.delete(:discard_layer_info) || discard_structure
|
113
|
-
# @tile_sets = nil if @properties.delete(:discard_tile_info) || discard_structure
|
114
|
-
@object_groups = nil if @properties.delete(:discard_object_info) || discard_structure
|
115
|
-
|
116
|
-
end # initialize
|
117
|
-
|
118
|
-
# def create_tile_set name, file_name_or_images, properties
|
119
|
-
# raise NotImplementedError
|
120
|
-
# end
|
121
|
-
|
122
|
-
def create_layer name, data, properties
|
123
|
-
raise NotImplementedError
|
6
|
+
class Map < OpenStruct
|
7
|
+
def layers
|
8
|
+
@layers ||= Array(contents['layers']).map {|layer| Layer.new layer.merge(contents: layer) }
|
124
9
|
end
|
125
|
-
|
126
|
-
def
|
127
|
-
|
10
|
+
|
11
|
+
def tilesets
|
12
|
+
@tilesets ||= Array(contents['tilesets']).map {|set| TileSet.new set.merge(contents: set) }
|
128
13
|
end
|
129
|
-
|
130
|
-
|
131
|
-
# @cache.draw x_off, y_off, z_off, x_range, y_range
|
132
|
-
@layers.each_value.with_index do |layer, index|
|
133
|
-
layer.draw x_off, y_off, z_off + index, x_range, y_range
|
134
|
-
end
|
135
|
-
end # draw
|
136
|
-
|
137
|
-
protected
|
138
|
-
|
139
|
-
def on_object name, group, properties
|
140
|
-
if @on_object
|
141
|
-
@on_object.call name, group, properties
|
142
|
-
else
|
143
|
-
properties
|
144
|
-
end
|
145
|
-
end # on_object
|
146
|
-
end # Map
|
147
|
-
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'oj'
|
2
|
+
|
3
|
+
module Tmx
|
4
|
+
module Parser
|
5
|
+
|
6
|
+
#
|
7
|
+
# Parses the JSON formatted output from Tiled.
|
8
|
+
#
|
9
|
+
class Json
|
10
|
+
attr_reader :options
|
11
|
+
|
12
|
+
def initialize(options)
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse(contents)
|
17
|
+
Oj.load(contents)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
Parsers.register :json, Parser::Json
|
24
|
+
end
|