tmx 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|