nuri_game-tmx_reader 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bafedf74686bf3db56b4075b3ee9dba4474f255cc4fe3d08c46c5bd6d2dd588a
4
+ data.tar.gz: 55d792e678149e79724ce7e70313be8a0be4c400d603c501db60d756bd0da5de
5
+ SHA512:
6
+ metadata.gz: 01ae0b8d7d024a892859268448299f17e2a597a8de4466f6057b44ac668a80c5489d3d77016f1db3d562b8cd92a939d37b9a18c271466a2523af36d1dc447cb1
7
+ data.tar.gz: 10d5816b916b005a63130674539a7eb7b04c1db9e5cc2eec7db60a17e60f52bb8a53656842733a543ba56cf8ac54926de4bbadb50a3df6d29730832f660669a4
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in nuri_game-tmx_reader.gemspec
6
+ gemspec
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # NuriGame::TmxReader
2
+
3
+ TMXReader that convert .tmx files to a ruby object
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'nuri_game-tmx_reader'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install nuri_game-tmx_reader
20
+
21
+ ## Usage
22
+
23
+ ```ruby
24
+ require 'nuri_game/tmx_reader'
25
+
26
+ # [...]
27
+
28
+ map = NuriGame::TmxReader.new('mapname.tmx')
29
+ # access here to map.layers, map.tilesets, map.width, map.height, map.tilewidth or map.tileheight
30
+ ```
31
+
32
+ ## Development
33
+
34
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
35
+
36
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
37
+
38
+ ## Contributing
39
+
40
+ Bug reports and pull requests are welcome at https://gitlab.com/NuriYuri/nuri_game-tmx_reader.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "nuri_game/tmx_reader"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ module NuriGame
2
+ class TmxReader
3
+ VERSION = "0.1.1"
4
+ end
5
+ end
@@ -0,0 +1,164 @@
1
+ require 'nuri_game/tmx_reader/version'
2
+ require 'rexml/document'
3
+ require 'zlib'
4
+ require 'base64'
5
+
6
+ # NuriGame namespace containing all the utility made by Nuri Yuri in order to make Games.
7
+ module NuriGame
8
+ # class that converts TMX file to Ruby object
9
+ class TmxReader
10
+
11
+ # Definition of a tileset
12
+ Tileset = Struct.new(:firstgid, :source)
13
+
14
+ # Constant holding the list of map information
15
+ MAP_INFOS = ['width', 'height', 'tilewidth', 'tileheight'].freeze
16
+
17
+ # @return [Integer] width of the map
18
+ attr_reader :width
19
+
20
+ # @return [Integer] height of the map
21
+ attr_reader :height
22
+
23
+ # @return [Integer] width of a tile on the map
24
+ attr_reader :tilewidth
25
+
26
+ # @return [Integer] height of a tile on the map
27
+ attr_reader :tileheight
28
+
29
+ # @return [Array<Tileset>] tilesets of the map
30
+ attr_reader :tilesets
31
+
32
+ # @return [Hash{String => Array<Integer>}] layers of the map (name => grid)
33
+ attr_reader :layers
34
+
35
+ # Create a new TmxReader
36
+ # @param filename [String] name of the tmx file to read
37
+ def initialize(filename)
38
+ contents = File.read(filename).force_encoding(Encoding::UTF_8)
39
+ map = REXML::Document.new(contents).root
40
+ @tilesets = []
41
+ @layers = {}
42
+ validate_map(map)
43
+ load_map_infos(map)
44
+ load_tilesets(map)
45
+ load_layers(map)
46
+ end
47
+
48
+ private
49
+
50
+ # Validate the map informations
51
+ # @parma map [REXML::Element]
52
+ def validate_map(map)
53
+ raise 'Invalid TMX data, root element is not a <map>' if map.name != 'map'
54
+ raise 'Invalid TMX orientation, expect orthogonal' if xml_value(map, 'orientation') != 'orthogonal'
55
+ raise 'Invalid TMX renderorder, expect left-up' if xml_value(map, 'renderorder') != 'left-up'
56
+ raise 'Invalid TMX map format, should not be infinite' if xml_value(map, 'infinite').to_i != 0
57
+ end
58
+
59
+ # Load the map informations
60
+ # @param map [REXML::Element]
61
+ def load_map_infos(map)
62
+ MAP_INFOS.each { |name| instance_variable_set(:"@#{name}", xml_value(map, name).to_i) }
63
+ end
64
+
65
+ # Load the map tilesets
66
+ # @param map [REXML::Element]
67
+ def load_tilesets(map)
68
+ tilesets = @tilesets
69
+ map.each_element('tileset') do |tileset|
70
+ tilesets << Tileset.new(xml_value(tileset, 'firstgid').to_i, xml_value(tileset, 'source').to_s)
71
+ end
72
+ end
73
+
74
+ # Load the map layers (flattened)
75
+ # @param map [REXML::Element]
76
+ def load_layers(map)
77
+ map.each_element_with_attribute('name') do |layer|
78
+ if layer.name == 'group'
79
+ load_layer_group(layer, xml_value(layer, 'name'))
80
+ elsif layer.name == 'layer'
81
+ @layers[xml_value(layer, 'name')] = load_layer(layer)
82
+ end
83
+ end
84
+ end
85
+
86
+ # Load the layer from a group
87
+ # @param group [REXML::Element]
88
+ # @param groupname [String]
89
+ def load_layer_group(group, groupname)
90
+ group.each_element do |layer|
91
+ if layer.name == 'group'
92
+ load_layer_group(layer, File.join(groupname, xml_value(layer, 'name')))
93
+ elsif layer.name == 'layer'
94
+ name = File.join(groupname, xml_value(layer, 'name'))
95
+ @layers[name] = load_layer(layer)
96
+ end
97
+ end
98
+ end
99
+
100
+ # Load the layer data
101
+ # @param layer [REXML::Element]
102
+ def load_layer(layer)
103
+ data = get_layer_data(layer)
104
+ # Perform stuff if there's offset & co (but shouldn't happen since we don't allow infinite maps)
105
+ return data
106
+ end
107
+
108
+ # Get the layer data
109
+ # @source https://github.com/shawn42/tmx/blob/master/lib/tmx/parsers/tmx-rexml.rb
110
+ # @param layer [REXML::Element]
111
+ def get_layer_data(layer)
112
+ data = REXML::XPath.first(layer, 'data')
113
+ enc = xml_value(data, 'encoding')
114
+ comp = xml_value(data, 'compression')
115
+ layer_data = REXML::XPath.first(layer, 'data').text.strip
116
+ layer_data = Base64.decode64(layer_data) if enc == 'base64'
117
+
118
+ case comp
119
+ when 'zlib'
120
+ return unpack_data(zlib_decompress(layer_data))
121
+ when 'gzip'
122
+ return unpack_data(gzip_decompress(layer_data))
123
+ else
124
+ case enc
125
+ when 'base64'
126
+ return unpack_data(layer_data)
127
+ when 'csv'
128
+ return layer_data.split(',').collect(&:to_i)
129
+ end
130
+ end
131
+ REXML::XPath.match(layer, "data/tile").map { |tile| tile.attributes["gid"].to_i }
132
+ end
133
+
134
+ # Decompress using Zlib
135
+ # @param data [String]
136
+ # @return [String]
137
+ def zlib_decompress(data)
138
+ Zlib::Inflate.inflate(data)
139
+ end
140
+
141
+ # Decompress using Gzip
142
+ # @param data [String]
143
+ # @return [String]
144
+ def gzip_decompress(data)
145
+ Zlib::GzipReader.new(StringIO.new(data)).read
146
+ end
147
+
148
+ # Convert data into valid Ruby Data
149
+ # @param data [String]
150
+ # @return [Array<Integer>]
151
+ def unpack_data(data)
152
+ data.unpack('V*')
153
+ end
154
+
155
+ # Return an xml value
156
+ # @param element [REXML::Element]
157
+ # @param value_name [String]
158
+ # @return [String, nil] nil means no value
159
+ def xml_value(element, value_name)
160
+ val = element.attribute(value_name)
161
+ return val ? val.value : nil
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,27 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "nuri_game/tmx_reader/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nuri_game-tmx_reader"
8
+ spec.version = NuriGame::TmxReader::VERSION
9
+ spec.authors = ["Nuri Yuri"]
10
+ spec.email = ["hostmaster@pokemonworkshop.com"]
11
+
12
+ spec.summary = %q{TMXReader that convert .tmx files to a ruby object}
13
+ spec.homepage = "https://gitlab.com/NuriYuri/nuri_game-tmx_reader"
14
+
15
+ # Specify which files should be added to the gem when it is released.
16
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+ spec.required_ruby_version = '>= 2.5.0'
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.16"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nuri_game-tmx_reader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Nuri Yuri
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-09-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description:
42
+ email:
43
+ - hostmaster@pokemonworkshop.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - README.md
51
+ - Rakefile
52
+ - bin/console
53
+ - bin/setup
54
+ - lib/nuri_game/tmx_reader.rb
55
+ - lib/nuri_game/tmx_reader/version.rb
56
+ - nuri_game-tmx_reader.gemspec
57
+ homepage: https://gitlab.com/NuriYuri/nuri_game-tmx_reader
58
+ licenses: []
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 2.5.0
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project:
76
+ rubygems_version: 2.7.3
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: TMXReader that convert .tmx files to a ruby object
80
+ test_files: []