dxruby_tiled 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/dxruby_tiled.rb CHANGED
@@ -1,25 +1,50 @@
1
- require "dxruby"
2
- require "json"
3
- require "zlib"
4
- require "base64"
1
+ require "dxruby" unless defined? DXRuby
2
+ require "json" unless defined? JSON
3
+ require "zlib" unless defined? Zlib
4
+ require "base64" unless defined? Base64
5
5
  require "dxruby_tiled/version"
6
6
  require "dxruby_tiled/map"
7
- require "dxruby_tiled/tilesets"
7
+ require "dxruby_tiled/tile"
8
8
  require "dxruby_tiled/tileset"
9
+ require "dxruby_tiled/tilesets"
9
10
  require "dxruby_tiled/layer"
11
+ require "dxruby_tiled/tilelayer"
10
12
  require "dxruby_tiled/layer_orthogonal"
11
13
  require "dxruby_tiled/layer_isometric"
12
14
  require "dxruby_tiled/layer_staggered"
13
15
  require "dxruby_tiled/layer_hexagonal"
14
- require "dxruby_tiled/objectgroup" # unsupported
16
+ require "dxruby_tiled/object"
17
+ require "dxruby_tiled/objectgroup"
15
18
  require "dxruby_tiled/imagelayer"
19
+ require "dxruby_tiled/grouplayer"
16
20
 
17
21
  module DXRuby
18
22
  module Tiled
19
- def self.load_json(jsonfile, encoding = "UTF-8", dir = nil)
20
- return Map.new(JSON.load(File.read(jsonfile, encoding: encoding), nil,
21
- symbolize_names: true, create_additions: false),
22
- dir || File.dirname(jsonfile))
23
+ module_function
24
+ autoload :TMXLoader, "dxruby_tiled/tmx_loader"
25
+
26
+ def load(file, encoding = Encoding::UTF_8, dir = nil)
27
+ case File.extname(file)
28
+ when ".tmx", ".xml"
29
+ TMXLoader.load_tmx(file, encoding, dir)
30
+ else
31
+ load_json(file, encoding, dir)
32
+ end
33
+ end
34
+
35
+ def read_file(file, encoding = Encoding::UTF_8)
36
+ File.read(file, encoding: encoding)
37
+ end
38
+
39
+ def load_json(jsonfile, encoding = Encoding::UTF_8, dir = nil)
40
+ Map.new(read_jsonfile(jsonfile, encoding), dir || File.dirname(jsonfile))
41
+ end
42
+
43
+ def read_jsonfile(jsonfile, encoding = Encoding::UTF_8)
44
+ JSON.parse(
45
+ read_file(jsonfile, encoding),
46
+ symbolize_names: true, create_additions: false
47
+ )
23
48
  end
24
49
  end
25
50
  end
@@ -0,0 +1,30 @@
1
+ module DXRuby
2
+ module Tiled
3
+ class GroupLayer < Layer
4
+ include Enumerable
5
+
6
+ def initialize(data, map)
7
+ super
8
+ @layers = data[:layers].map do |layer|
9
+ Layer.create(layer, map)
10
+ end
11
+ end
12
+
13
+ def [](name)
14
+ return @layers[name] if name.is_a? Integer
15
+ return @layers.find { |layer| layer.name == name }
16
+ end
17
+
18
+ def each
19
+ @layers.each { |layer| yield layer }
20
+ end
21
+
22
+ def render(x, y, target = DXRuby::Window, z = 0, offset_x = 0, offset_y = 0, opacity = 1.0)
23
+ @layers.each do |layer|
24
+ layer.render(x, y, target, z + @z_index, offset_x + @offset_x, offset_y + @offset_y, opacity * @opacity) if layer.visible
25
+ end
26
+ end
27
+ alias_method :draw, :render
28
+ end
29
+ end
30
+ end
@@ -1,35 +1,51 @@
1
1
  module DXRuby
2
2
  module Tiled
3
- class ImageLayer
4
- attr_reader :data, :name, :properties
5
- attr_accessor :opacity, :visible, :offset_x, :offset_y, :fixed
3
+ class ImageLayer < Layer
4
+ attr_accessor :image, :fixed, :x_loop, :y_loop
6
5
 
7
6
  def initialize(data, map)
8
- @original_data = data
9
- @map = map
7
+ super
8
+ @x_loop = !!@properties[:x_loop]
9
+ @y_loop = !!@properties[:y_loop]
10
+ @image = map.load_image(data[:image], data[:transparentcolor])
11
+ @map_loop = map.loop
12
+ @map_pixel_width = map.pixel_width
13
+ @map_pixel_height = map.pixel_height
14
+ end
15
+
16
+ def render(x, y, target = DXRuby::Window, z = 0, offset_x = 0, offset_y = 0, opacity = 1.0)
17
+ x_range = 0..0
18
+ if @x_loop
19
+ x0 = (@offset_x + offset_x - (@fixed? 0 : x)) % @image.width
20
+ x_range = -1..((target.width - 1) / @image.width)
21
+ elsif @fixed
22
+ x0 = @offset_x + offset_x
23
+ elsif @map_loop
24
+ x0 = (@offset_x + offset_x - x + target.width) % @map_pixel_width - target.width
25
+ else
26
+ x0 = @offset_x + offset_x - x
27
+ end
10
28
 
11
- @name = data[:name]
12
- @opacity = data[:opacity] || 1.0
13
- @visible = data[:visible] != false
14
- @offset_x = data[:offsetx] || 0
15
- @offset_y = data[:offsety] || 0
16
- @properties = data[:properties] || {}
17
- @fixed = @properties[:fixed]
29
+ y_range = 0..0
30
+ if @y_loop
31
+ y0 = (@offset_y + offset_y - (@fixed? 0 : y)) % @image.height
32
+ y_range = -1..((target.height - 1) / @image.height)
33
+ elsif @fixed
34
+ y0 = @offset_y + offset_y
35
+ elsif @map_loop
36
+ y0 = (@offset_y + offset_y - y + target.height) % @map_pixel_height - target.height
37
+ else
38
+ y0 = @offset_y + offset_y - y
39
+ end
18
40
 
19
- @image = @map.load_image(data[:image])
20
- if data[:transparentcolor]
21
- color = data[:transparentcolor].sub("#", "").scan(/../).map{|c| c.to_i(16) }
22
- @image.set_color_key(color)
41
+ x_range.each do |i_x|
42
+ y_range.each do |i_y|
43
+ target.draw_alpha(x0 + @image.width * i_x, y0 + @image.height * i_y,
44
+ @image, 255 * opacity * @opacity, z + @z_index)
45
+ end
23
46
  end
24
47
  end
25
-
26
- def draw(x, y, target = DXRuby::Window)
27
- x = (x + target.width) % @map.pixel_width - target.width if @map.x_loop
28
- y = (y + target.height) % @map.pixel_height - target.height if @map.y_loop
29
- target.draw_alpha(@offset_x - (@fixed ? 0 : x), @offset_y - (@fixed? 0 : y),
30
- @image, (255 * @opacity).to_i)
31
- end
32
-
48
+ alias_method :draw, :render
33
49
  end
34
50
  end
35
51
  end
@@ -1,55 +1,32 @@
1
1
  module DXRuby
2
2
  module Tiled
3
3
  class Layer
4
- attr_reader :data, :name, :width, :height, :properties
5
- attr_accessor :opacity, :visible, :offset_x, :offset_y
4
+ attr_reader :name, :properties
5
+ attr_accessor :opacity, :visible, :offset_x, :offset_y, :z_index
6
+
7
+ def self.create(data, map)
8
+ case data[:type]
9
+ when "tilelayer"
10
+ map.orientation.new(data, map)
11
+ when "objectgroup"
12
+ DXRuby::Tiled::ObjectGroup.new(data, map)
13
+ when "imagelayer"
14
+ DXRuby::Tiled::ImageLayer.new(data, map)
15
+ when "group"
16
+ DXRuby::Tiled::GroupLayer.new(data, map)
17
+ end
18
+ end
6
19
 
7
20
  def initialize(data, map)
8
- @map = map
9
-
10
21
  @name = data[:name]
11
- @width = data[:width ] || map.width
12
- @height = data[:height] || map.height
13
22
  @opacity = data[:opacity] || 1.0
14
23
  @visible = data[:visible] != false
15
24
  @offset_x = data[:offsetx] || 0
16
25
  @offset_y = data[:offsety] || 0
17
26
  @properties = data[:properties] || {}
18
-
19
- case data[:encoding]
20
- when "base64"
21
- tmp = Base64.decode64(data[:data])
22
- case data[:compression]
23
- when "gzip" # unsupported
24
- when "zlib"
25
- tmp = Zlib::Inflate.inflate(tmp).unpack("l*")
26
- else
27
- tmp = tmp.unpack("l*")
28
- end
29
- else
30
- tmp = data[:data]
31
- end
32
- @data = tmp.each_slice(@width).to_a
33
- end
34
-
35
- def [](x, y)
36
- x = @map.x_loop ? x % @width : x < 0 ? @width : x
37
- y = @map.y_loop ? y % @height : y < 0 ? @height : y
38
- return @data.fetch(y, []).fetch(x, 0)
27
+ @z_index = @properties[:z_index] || 0
28
+ @fixed = !!@properties[:fixed]
39
29
  end
40
-
41
- def []=(x, y, value)
42
- x = @map.x_loop ? x % @width : x < 0 ? @width : x
43
- y = @map.y_loop ? y % @height : y < 0 ? @height : y
44
- @data[y][x] = value
45
- end
46
-
47
- def include?(x, y)
48
- return (@map.x_loop || (0...@width).include?(x)) &&
49
- (@map.y_loop || (0...@height).include?(y))
50
- end
51
- alias_method :member?, :include?
52
-
53
30
  end
54
31
  end
55
32
  end
@@ -1,133 +1,136 @@
1
1
  module DXRuby
2
2
  module Tiled
3
- class HexagonalLayer < Layer
3
+ class HexagonalLayer < TileLayer
4
+ def initialize(data, map)
5
+ super
6
+ @stagger_axis_y = map.stagger_axis_y
7
+ @stagger_index_odd = map.stagger_index_odd
8
+ @hex_side_length = map.hex_side_length
9
+ end
4
10
 
5
- def draw(x, y, target = DXRuby::Window)
6
- tile_images = @map.tilesets.tile_images
7
- left, top = xy_at(x - @offset_x, y - @offset_x)
8
- left -= 1
9
- top -= 1
10
- off_x = x - @map.tile_width / 2 + @offset_x
11
- off_y = y - @map.tile_height / 2 + @offset_y
12
- alpha = (@opacity * 255).floor
11
+ def render(pos_x, pos_y, target = DXRuby::Window, z = @z_index, offset_x = 0, offset_y = 0, opacity = 1.0)
12
+ super
13
+
14
+ pos_x, pos_y = 0, 0 if @fixed
15
+ off_x = offset_x + @offset_x - pos_x
16
+ off_y = offset_y + @offset_y - pos_y
17
+ x1, y1 = xy_at(@tile_width - @tilesets.tile_right - off_x,
18
+ @tile_height - @tilesets.tile_bottom - off_y)
19
+ x2, y2 = xy_at(@render_target.width - @tilesets.tile_left - off_x - 1,
20
+ @render_target.height - @tilesets.tile_top - off_y - 1)
21
+ x_range = ((x1 - 1)..(x2 + 1))
22
+ y_range = ((y1 - 1)..(y2 + 1))
13
23
 
14
- if @map.stagger_axis_y
15
- tile_width = @map.tile_width
16
- tile_height = @map.tile_height - (@map.tile_height - @map.hex_side_length) / 2
17
- x_range = left..(left + target.width / tile_width + 3).floor
18
- y_range = top..(top + target.height / tile_height + 2).floor
19
-
20
- y_range.each do |y2|
21
- x0 = @map.stagger_index_odd ^ y2.even? ? tile_width / 2 : 0
22
- x_range.each do |x2|
23
- image = tile_images[self[x2, y2]]
24
- target.draw_alpha(x0 + x2 * tile_width - off_x - image.width / 2,
25
- y2 * tile_height - off_y - image.height / 2,
26
- image, alpha)
24
+ if @stagger_axis_y
25
+ tile_width = @tile_width
26
+ tile_height = @tile_height - (@tile_height - @hex_side_length) / 2
27
+ y_range.public_send(@renderorder_y ? :each : :reverse_each) do |y|
28
+ x0 = @stagger_index_odd ^ y.even? ? tile_width / 2 : 0
29
+ x_range.public_send(@renderorder_x ? :each : :reverse_each) do |x|
30
+ @tilesets[self[x, y]].render(
31
+ x * tile_width + off_x + x0,
32
+ y * tile_height + off_y,
33
+ @render_target)
27
34
  end
28
35
  end
29
36
  else
30
- tile_width = @map.tile_width - (@map.tile_width - @map.hex_side_length) / 2
31
- tile_height = @map.tile_height
32
- x_range = left..(left + target.width / tile_width + 2).floor
33
- y_range = top..(top + target.height / tile_height + 3).floor
34
-
35
- y_range.each do |y2|
36
- x_range.each do |x2|
37
- y0 = @map.stagger_index_odd ^ x2.even? ? tile_height / 2 : 0
38
- image = tile_images[self[x2, y2]]
39
- target.draw_alpha( x2 * tile_width - off_x - image.width / 2,
40
- y0 + y2 * tile_height - off_y - image.height / 2,
41
- image, alpha)
37
+ tile_width = @tile_width - (@tile_width - @hex_side_length) / 2
38
+ tile_height = @tile_height
39
+ y_range.public_send(@renderorder_y ? :each : :reverse_each) do |y|
40
+ x_range.public_send(@renderorder_x ? :each : :reverse_each) do |x|
41
+ next if @stagger_index_odd ^ x.even?
42
+ @tilesets[self[x, y]].render(
43
+ x * tile_width + off_x,
44
+ y * tile_height + off_y,
45
+ @render_target)
46
+ end
47
+ x_range.public_send(@renderorder_x ? :each : :reverse_each) do |x|
48
+ next unless @stagger_index_odd ^ x.even?
49
+ @tilesets[self[x, y]].render(
50
+ x * tile_width + off_x,
51
+ y * tile_height + off_y + tile_height / 2,
52
+ @render_target)
42
53
  end
43
54
  end
44
55
  end
56
+
57
+ target.draw_alpha(0, 0, @render_target, @opacity * 255, z + @z_index)
45
58
  end
59
+ alias_method :draw, :render
46
60
 
47
- def xy_at(x, y)
48
- if @map.stagger_axis_y
49
- height = @map.tile_height - (@map.tile_height - @map.hex_side_length) / 2
50
- y2 = y / height
51
- x -= @map.tile_width / 2 if @map.stagger_index_odd ^ y2.even?
52
- x2 = x / @map.tile_width
53
- x0 = x % @map.tile_width
54
- y0 = y % height
55
- if (y0 < (@map.tile_height - height) - x0 * (@map.tile_height - height) * 2 / @map.tile_width)
56
- y2 -= 1
57
- x2 += @map.stagger_index_odd ^ y2.even? ? -1 : 0
58
- elsif (y0 < x0 * (@map.tile_height - height) * 2 / @map.tile_width - (@map.tile_height - height))
59
- y2 -= 1
60
- x2 += @map.stagger_index_odd ^ y2.even? ? 0 : 1
61
+ def xy_at(pos_x, pos_y)
62
+ if @stagger_axis_y
63
+ height = @tile_height - (@tile_height - @hex_side_length) / 2
64
+ y = (pos_y / height).floor
65
+ pos_x -= @tile_width / 2 if @stagger_index_odd ^ y.even?
66
+ x = (pos_x / @tile_width).floor
67
+ dx = pos_x % @tile_width
68
+ dy = pos_y % height
69
+ if (dy < (@tile_height - height) - dx * (@tile_height - height) * 2 / @tile_width)
70
+ y -= 1
71
+ x += @stagger_index_odd ^ y.even? ? -1 : 0
72
+ elsif (dy < dx * (@tile_height - height) * 2 / @tile_width - (@tile_height - height))
73
+ y -= 1
74
+ x += @stagger_index_odd ^ y.even? ? 0 : 1
61
75
  end
62
76
  else
63
- width = @map.tile_width - (@map.tile_width - @map.hex_side_length) / 2
64
- x2 = x / width
65
- y -= @map.tile_height / 2 if @map.stagger_index_odd ^ x2.even?
66
- y2 = y / @map.tile_height
67
- x0 = x % width
68
- y0 = y % @map.tile_height
69
- if (y0 < @map.height / 2 - x0 * @map.tile_height / (@map.tile_width - width) / 2)
70
- x2 -= 1
71
- y2 += @map.stagger_index_odd ^ x2.even? ? -1 : 0
72
- elsif (y0 > @map.height / 2 + x0 * @map.tile_height / (@map.tile_width - width) / 2)
73
- x2 -= 1
74
- y2 += @map.stagger_index_odd ^ x2.even? ? 0 : 1
77
+ width = @tile_width - (@tile_width - @hex_side_length) / 2
78
+ x = (pos_x / width).floor
79
+ pos_y -= @tile_height / 2 if @stagger_index_odd ^ x.even?
80
+ y = (pos_y / @tile_height).floor
81
+ dx = pos_x % width
82
+ dy = pos_y % @tile_height
83
+ if (dy * 2 < @tile_height - dx * @tile_height / (@tile_width - width))
84
+ x -= 1
85
+ y += @stagger_index_odd ^ x.even? ? -1 : 0
86
+ elsif (dy > @tile_height / 2 + dx * @tile_height / (@tile_width - width) / 2)
87
+ x -= 1
88
+ y += @stagger_index_odd ^ x.even? ? 0 : 1
75
89
  end
76
90
  end
77
- return x2, y2
78
- end
79
-
80
- def at(x, y)
81
- tmp_x, tmp_y = xy_at(x, y)
82
- return self[tmp_x, tmp_y]
83
- end
84
-
85
- def change_at(x, y, value)
86
- tmp_x, tmp_y = xy_at(x, y)
87
- self[tmp_x, tmp_y] = value
91
+ return x, y
88
92
  end
89
93
 
90
94
  def vertexs(x, y)
91
- if @map.stagger_axis_y
92
- w, h = @map.tile_width / 2, @map.tile_height - (@map.tile_height - @map.hex_side_length) / 2
93
- x0 = @map.stagger_index_odd ^ y.even? ? w : 0
95
+ if @stagger_axis_y
96
+ w, h = @tile_width / 2, @tile_height - (@tile_height - @hex_side_length) / 2
97
+ x0 = @stagger_index_odd ^ y.even? ? w : 0
94
98
  return [
95
99
  [ x0 + x * w * 2 + w , y * h ],
96
- [ x0 + x * w * 2 , y * h + h - @map.hex_side_length ],
100
+ [ x0 + x * w * 2 , y * h + h - @hex_side_length ],
97
101
  [ x0 + x * w * 2 , y * h + h ],
98
- [ x0 + x * w * 2 + w , y * h + @map.tile_height ],
102
+ [ x0 + x * w * 2 + w , y * h + @tile_height ],
99
103
  [ x0 + x * w * 2 + w * 2, y * h + h ],
100
- [ x0 + x * w * 2 + w * 2, y * h + h - @map.hex_side_length ]
104
+ [ x0 + x * w * 2 + w * 2, y * h + h - @hex_side_length ]
101
105
  ]
102
106
  else
103
- w, h = @map.tile_width - (@map.tile_width - @map.hex_side_length) / 2, @map.tile_height / 2
104
- y0 = @map.stagger_index_odd ^ x.even? ? h : 0
107
+ w, h = @tile_width - (@tile_width - @hex_side_length) / 2, @tile_height / 2
108
+ y0 = @stagger_index_odd ^ x.even? ? h : 0
105
109
  return [
106
- [ x * w, y0 + y * h * 2 + h , y * h ],
107
- [ x * w + w - @map.hex_side_length, y0 + y * h * 2 ],
108
- [ x * w + w , y0 + y * h * 2 ],
109
- [ x * w + @map.tile_width , y0 + y * h * 2 + h ],
110
- [ x * w + w , y0 + y * h * 2 + h * 2 ],
111
- [ x * w + w - @map.hex_side_length, y0 + y * h * 2 + h * 2 ]
110
+ [ x * w, y0 + y * h * 2 + h , y * h ],
111
+ [ x * w + w - @hex_side_length, y0 + y * h * 2 ],
112
+ [ x * w + w , y0 + y * h * 2 ],
113
+ [ x * w + @tile_width , y0 + y * h * 2 + h ],
114
+ [ x * w + w , y0 + y * h * 2 + h * 2 ],
115
+ [ x * w + w - @hex_side_length, y0 + y * h * 2 + h * 2 ]
112
116
  ]
113
117
  end
114
118
  end
115
119
 
116
120
 
117
121
  def self.pixel_width(map)
118
- return map.stagger_axis_y ?
119
- map.tile_width * (map.tile_width - (map.tile_width - map.hex_side_length) / 2) +
120
- (map.tile_width - map.hex_side_length) / 2 :
121
- map.tile_width * (map.width + 1) / 2
122
+ map.stagger_axis_y ?
123
+ map.tile_width * (map.tile_width - (map.tile_width - map.hex_side_length) / 2) +
124
+ (map.tile_width - map.hex_side_length) / 2 :
125
+ map.tile_width * (map.width + 1) / 2
122
126
  end
123
127
 
124
128
  def self.pixel_height(map)
125
- return map.stagger_axis_y ?
126
- map.tile_height * (map.height + 1) / 2 :
127
- map.tile_height * (map.tile_height - (map.tile_height - map.hex_side_length) / 2) +
128
- (map.tile_height - map.hex_side_length) / 2
129
+ map.stagger_axis_y ?
130
+ map.tile_height * (map.height + 1) / 2 :
131
+ map.tile_height * (map.tile_height - (map.tile_height - map.hex_side_length) / 2) +
132
+ (map.tile_height - map.hex_side_length) / 2
129
133
  end
130
-
131
134
  end
132
135
  end
133
136
  end