dxruby_tiled 0.1.0 → 1.0.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.
@@ -0,0 +1,263 @@
1
+ module DXRuby
2
+ module Tiled
3
+ class TMEObject < DXRuby::Sprite
4
+ attr_reader :object_id, :properties
5
+ attr_accessor :name, :type
6
+
7
+ def self.create_from_hash(hash, map = nil)
8
+ hash[:id] ||= map.next_object_id
9
+ if hash[:template]
10
+ template = map.load_template(hash[:template])
11
+ gid, source = template[:object][:gid], template[:tileset][:source]
12
+ template[:object][:gid] = map.tilesets.gid_adjusted_by_source(gid, source)
13
+ hash.merge!(template[:object])
14
+ end
15
+ object = case
16
+ when hash[:point]
17
+ PointObject.create_from_hash(hash)
18
+ when hash[:ellipse]
19
+ EllipseObject.create_from_hash(hash)
20
+ when hash[:polygon]
21
+ PolygonObject.create_from_hash(hash)
22
+ when hash[:polyline]
23
+ PolylineObject.create_from_hash(hash)
24
+ when hash[:text]
25
+ TextObject.create_from_hash(hash)
26
+ when hash[:gid]
27
+ hash[:tile] = map.tilesets[hash[:gid]]
28
+ TileObject.create_from_hash(hash)
29
+ else
30
+ RectangleObject.create_from_hash(hash)
31
+ end
32
+ if map && map.orientation == IsometricLayer
33
+ object.extend(ObjectInIsometricMap)
34
+ object.width_height = 1.0 * map.tile_height / map.tile_width
35
+ end
36
+ object
37
+ end
38
+
39
+ def initialize(x, y, options = {})
40
+ super x, y, nil
41
+ @name = options[:name]
42
+ @type = options[:type]
43
+ @object_id = options[:id]
44
+ @width = options[:width]
45
+ @height = options[:height]
46
+ @properties = options[:properties]
47
+ self.angle = options[:rotation]
48
+ self.visible = options[:visible]
49
+ self.collision_sync = true
50
+ end
51
+ end
52
+
53
+ class PointObject < TMEObject
54
+ def self.create_from_hash(hash)
55
+ self.new(hash[:x], hash[:y], hash)
56
+ end
57
+
58
+ def initialize(x, y, width, height, options = {})
59
+ super x, y, options
60
+ self.collision = [0, 0]
61
+ end
62
+
63
+ def draw; end
64
+ end
65
+
66
+ class RectangleObject < TMEObject
67
+ def self.create_from_hash(hash)
68
+ self.new(hash[:x], hash[:y], hash[:width], hash[:height], hash)
69
+ end
70
+
71
+ def initialize(x, y, width, height, options = {})
72
+ options[:width] = width
73
+ options[:height] = height
74
+ super x, y, options
75
+ self.collision = [0, 0, @width, @height]
76
+ end
77
+
78
+ def draw; end
79
+ end
80
+
81
+ class EllipseObject < TMEObject
82
+ def self.create_from_hash(hash)
83
+ self.new(hash[:x], hash[:y], hash[:width], hash[:height], hash)
84
+ end
85
+
86
+ def initialize(x, y, width, height, options = {})
87
+ options[:width] = width
88
+ options[:height] = height
89
+ super x, y, options
90
+ self.collision = [@width / 2.0, @width / 2.0, @width / 2.0]
91
+ self.scale_y = 1.0 * @height / @width
92
+ end
93
+
94
+ def draw; end
95
+ end
96
+
97
+ class PolygonObject < TMEObject
98
+ def self.create_from_hash(hash)
99
+ self.new(hash[:x], hash[:y], hash[:polygon], hash)
100
+ end
101
+
102
+ def initialize(x, y, vertexs, options)
103
+ super x, y, options
104
+ collision = []
105
+ (vertexs.size - 2).times do |i|
106
+ collision.push([vertexs[0 ][:x], vertexs[0 ][:y],
107
+ vertexs[i + 1][:x], vertexs[i + 1][:y],
108
+ vertexs[i + 2][:x], vertexs[i + 2][:y]])
109
+ end
110
+ self.collision = collision
111
+ end
112
+
113
+ def draw; end
114
+ end
115
+
116
+ class PolylineObject < TMEObject
117
+ def self.create_from_hash(hash)
118
+ self.new(hash[:x], hash[:y], hash[:polyline], hash)
119
+ end
120
+
121
+ def initialize(x, y, vertexs, options)
122
+ super x, y, options
123
+ collision = []
124
+ (vertexs.size - 2).times do |i|
125
+ collision.push([vertexs[0 ][:x], vertexs[0 ][:y],
126
+ vertexs[i + 1][:x], vertexs[i + 1][:y],
127
+ vertexs[i + 2][:x], vertexs[i + 2][:y]])
128
+ end
129
+ self.collision = collision
130
+ end
131
+
132
+ def draw; end
133
+ end
134
+
135
+ class TextObject < TMEObject
136
+ attr_accessor :text
137
+
138
+ def self.create_from_hash(hash)
139
+ self.new(hash[:x], hash[:y], hash[:width], hash[:height], hash[:text][:text], hash[:text])
140
+ end
141
+
142
+ def initialize(x, y, width, height, text, options = {})
143
+ options[:width] = width
144
+ options[:height] = height
145
+ super x, y, options
146
+ @text = text
147
+ @fontfamily = options[:fontfamily] || ""
148
+ @pixelsize = options[:pixelsize] || 16
149
+ @wrap = !!options[:wrap] # unsupported
150
+ @color = (options[:color] || "000000").sub("#", "").scan(/../).map{ |c| c.to_i(16) }
151
+ @bold = !!options[:bold]
152
+ @italic = !!options[:italic]
153
+ @underline = !!options[:underline] # unsupported
154
+ @strikeout = !!options[:strikeout] # unsupported
155
+ @kerning = options[:kerning] != false # unsupported
156
+ @halign = options[:halign] || "left" # unsupported
157
+ @valign = options[:valign] || "top" # unsupported
158
+
159
+ @font = DXRuby::Font.new(@pixelsize, @fontfamily,
160
+ weight: @bold, italic: @italic, auto_fitting: true
161
+ )
162
+ self.collision = [0, 0, @width, @height]
163
+ end
164
+
165
+ def draw
166
+ self.target.draw_font(self.x, self.y, @text, @font,
167
+ color: @color, center_x: 0, center_y: 0, angle: self.angle, z: self.z
168
+ )
169
+ end
170
+ end
171
+
172
+ class TileObject < TMEObject
173
+ attr_reader :tile
174
+ attr_accessor :start_time
175
+
176
+ def self.evolve(object)
177
+ new_object = self.new(x: object.x, y: object.y, tile: object.tile, id: @object_id)
178
+ %w[z angle scale_x scale_y center_x center_y
179
+ alpha blend shader image target
180
+ collision collision_enable collision_sync visible offset_sync
181
+ name type start_time].each do |arg|
182
+ new_object.send(arg + "=", object.send(arg))
183
+ end
184
+ end
185
+
186
+ def self.create_from_hash(hash)
187
+ self.new(hash[:x], hash[:y], hash[:tile], hash)
188
+ end
189
+
190
+ def initialize(x, y, tile, options = {})
191
+ super x, y, options
192
+ @tile = tile
193
+ self.image = tile.original_image
194
+ if tile.is_a? FlippedTile
195
+ self.scale_x = tile.scale_x
196
+ self.scale_y = tile.scale_y
197
+ @tile = tile.tile
198
+ self.extend(FlippedTileObject)
199
+ end
200
+ self.angle = options[:rotation]
201
+ self.center_x = -tile.offset_x
202
+ self.center_y = self.image.height - tile.offset_y
203
+ self.collision = tile.collision
204
+ self.collision_enable = tile.collision_enable
205
+ self.offset_sync = true
206
+ @start_time = nil
207
+ end
208
+
209
+ def draw
210
+ @start_time ||= DXRuby::Window::running_time
211
+ tile = @tile.animate((DXRuby::Window::running_time - @start_time))
212
+ self.image = tile.original_image
213
+ self.center_x = -tile.offset_x
214
+ self.center_y = self.image.height - tile.offset_y
215
+ super
216
+ end
217
+
218
+ def tile=(tile)
219
+ @tile = tile
220
+ @start_time = nil
221
+ end
222
+
223
+ def become(new_class)
224
+ new_class.evolve(self)
225
+ end
226
+ end
227
+
228
+ module FlippedTileObject
229
+ def draw
230
+ @start_time ||= DXRuby::Window::running_time
231
+ tile = @tile.animate((DXRuby::Window::running_time - @start_time))
232
+ self.image = tile.original_image
233
+ sin = Math.sin(2 * Math::PI * self.angle / 360)
234
+ cos = Math.cos(2 * Math::PI * self.angle / 360)
235
+ cx = (self.image.width * 0.5 + tile.offset_x) * self.scale_x.abs
236
+ cy = (self.image.height * 0.5 - tile.offset_y) * self.scale_y.abs
237
+ x = self.x + cx * cos + cy * sin
238
+ y = self.y - cy * cos + cx * sin
239
+ self.target.draw_ex(x, y, self.image,
240
+ scale_x: self.scale_x,
241
+ scale_y: self.scale_y,
242
+ alpha: self.alpha,
243
+ blend: self.blend,
244
+ angle: self.angle,
245
+ shader: self.shader,
246
+ z: self.z,
247
+ offset_sync: true
248
+ )
249
+ end
250
+ end
251
+
252
+ module ObjectInIsometricMap
253
+ attr_accessor :width_height
254
+ def draw
255
+ tmp_x, tmp_y = self.x, self.y
256
+ self.x = tmp_x - tmp_y
257
+ self.y = (tmp_x + tmp_y) * @width_height
258
+ super
259
+ self.x, self.y = tmp_x, tmp_y
260
+ end
261
+ end
262
+ end
263
+ end
@@ -1,26 +1,47 @@
1
1
  module DXRuby
2
2
  module Tiled
3
- class ObjectGroup # unsupported
4
- attr_reader :data, :name, :width, :height, :properties
5
- attr_accessor :opacity, :visible, :offset_x, :offset_y
3
+ class ObjectGroup < Layer
4
+ attr_reader :x, :y, :width, :height, :draworder, :objects
6
5
 
7
6
  def initialize(data, map)
8
- @original_data = data
9
- @map = map
7
+ super
8
+ @x = data[:x] || 0
9
+ @y = data[:y] || 0
10
+ @width = data[:width ] || map.width
11
+ @height = data[:height] || map.height
12
+ @draworder = data[:draworder] || "topdown"
10
13
 
11
- @name = data[:name]
12
- @color = data[:color] || [128, 128, 128]
13
- @opacity = data[:opacity] || 1
14
- @visible = data[:visible] != false
15
- @offset_x = data[:offsetx] || 0
16
- @offset_y = data[:offsety] || 0
17
- @properties = data[:properties] || {}
18
- @draworder = data[:draworder] || "topdown"
14
+ @render_target = DXRuby::RenderTarget.new(DXRuby::Window.width, DXRuby::Window.height)
15
+ @objects = data[:objects].map do |object_hash|
16
+ object = TMEObject.create_from_hash(object_hash, map)
17
+ object.target = @render_target
18
+ if object.is_a? TileObject
19
+ object.scale_x = 1.0 * object_hash[:width ] / object.image.width * object.scale_x
20
+ object.scale_y = 1.0 * object_hash[:height] / object.image.height * object.scale_y
21
+ end
22
+ object
23
+ end
19
24
  end
20
25
 
21
- def draw(x, y, target = DXRuby::Window)
26
+ def render(x, y, target = DXRuby::Window, z = 0, offset_x = 0, offset_y = 0, opacity = 1.0)
27
+ if @render_target.width != target.width || @render_target.height != target.height
28
+ @render_target.resize(target.width, target.height)
29
+ end
30
+ @render_target.ox = offset_x + @offset_x + (@fixed ? 0 : x)
31
+ @render_target.oy = offset_y + @offset_y + (@fixed ? 0 : y)
32
+
33
+ DXRuby::Sprite.update(@objects)
34
+ DXRuby::Sprite.clean(@objects)
35
+ DXRuby::Sprite.draw(
36
+ case @draworder
37
+ when "topdown" then @objects.sort_by { |obj| obj.y }
38
+ when "index" then @objects.sort_by { |obj| obj.object_id }
39
+ else @objects
40
+ end
41
+ )
42
+ target.draw_alpha(0, 0, @render_target, @opacity * 255, z + @z_index)
22
43
  end
23
-
44
+ alias_method :draw, :render
24
45
  end
25
46
  end
26
47
  end
@@ -0,0 +1,139 @@
1
+ module DXRuby
2
+ module Tiled
3
+ class Tile
4
+ attr_reader :image, :original_image, :offset_x, :offset_y, :adjusted_offset_y, :tileset,
5
+ :scale_x, :scale_y, :angle
6
+ attr_accessor :type, :collision, :collision_enable
7
+
8
+ def initialize(image, offset_x, offset_y, adjusted_offset_y, tileset = nil)
9
+ @image = @original_image = image
10
+ @offset_x = offset_x
11
+ @offset_y = offset_y
12
+ @adjusted_offset_y = adjusted_offset_y
13
+ @tileset = tileset
14
+ @type = nil
15
+ @anim_time_total = 1
16
+ @anim_time = [0]
17
+ @anim_tile = [self]
18
+ @collision = nil
19
+ @collision_enable = true
20
+ @scale_x = 1
21
+ @scale_y = 1
22
+ @angle = 0
23
+ end
24
+
25
+ def width ; @image.width ; end
26
+ def height; @image.height; end
27
+
28
+ def render(x, y, target = DXRuby::Window, z_index = 0)
29
+ target.draw(x + @offset_x, y + @adjusted_offset_y, @image, z_index)
30
+ end
31
+ alias_method :draw, :render
32
+
33
+ def animate(current_time)
34
+ time = current_time % @anim_time_total
35
+ @anim_tile[@anim_time.rindex { |t| time >= t } ]
36
+ end
37
+
38
+ def animate!(current_time)
39
+ time = current_time % @anim_time_total
40
+ tile = @anim_tile[@anim_time.rindex { |t| time >= t } ]
41
+ @image = tile.original_image
42
+ @offset_x = tile.offset_x
43
+ @offset_y = tile.offset_y
44
+ @adjusted_offset_y = tile.adjusted_offset_y
45
+ end
46
+
47
+ def set_animation(anim_time, anim_tile)
48
+ @anim_time = anim_time
49
+ @anim_tile = anim_tile
50
+ @anim_time_total = @anim_time.pop
51
+ end
52
+
53
+ def to_sprite(x, y)
54
+ TileObject.new(x: x, y: y, tile: self)
55
+ end
56
+ end
57
+
58
+ class FlippedTile
59
+ attr_reader :scale_x, :scale_y, :angle, :tile
60
+
61
+ def initialize(tile, tileid, hex = false)
62
+ @tile = tile
63
+ if hex
64
+ @scale_x, @scale_y, @angle = case tileid & 0xf0000000
65
+ when 0x10000000 then [ 1, 1, 120]
66
+ when 0x20000000 then [ 1, 1, 60]
67
+ when 0x30000000 then [-1, -1, 0]
68
+ when 0x40000000 then [ 1, -1, 0]
69
+ when 0x50000000 then [-1, 1, 300]
70
+ when 0x60000000 then [-1, 1, 240]
71
+ when 0x70000000 then [-1, 1, 0]
72
+ when 0x80000000 then [-1, 1, 0]
73
+ when 0x90000000 then [-1, 1, 120]
74
+ when 0xa0000000 then [-1, 1, 60]
75
+ when 0xb0000000 then [ 1, -1, 0]
76
+ when 0xc0000000 then [-1, -1, 0]
77
+ when 0xd0000000 then [ 1, 1, 300]
78
+ when 0xe0000000 then [ 1, 1, 240]
79
+ when 0xf0000000 then [ 1, 1, 0]
80
+ end
81
+ else
82
+ @scale_x, @scale_y, @angle = case tileid & 0xe0000000
83
+ when 0x20000000 then [ 1, -1, 90]
84
+ when 0x40000000 then [ 1, -1, 0]
85
+ when 0x60000000 then [-1, -1, 90]
86
+ when 0x80000000 then [-1, 1, 0]
87
+ when 0xa0000000 then [ 1, 1, 90]
88
+ when 0xc0000000 then [-1, -1, 0]
89
+ when 0xe0000000 then [-1, 1, 90]
90
+ end
91
+ end
92
+ extend DXRuby::Tiled::DiagonallyFlippedTile if @angle == 90
93
+ end
94
+
95
+ def render(x, y, target=DXRuby::Window, z_index = 0)
96
+ target.draw_ex(x + offset_x, y + adjusted_offset_y, @tile.image,
97
+ { scale_x: @scale_x, scale_y: @scale_y, angle: @angle, z: z_index })
98
+ end
99
+ alias_method :draw, :render
100
+
101
+ def width; @tile.width; end
102
+ def height; @tile.height; end
103
+ def image; @tile.image; end
104
+ def original_image; @tile.original_image; end
105
+ def offset_x; @tile.offset_x; end
106
+ def offset_y; @tile.offset_y; end
107
+ def adjusted_offset_y; @tile.adjusted_offset_y; end
108
+ def tileset; @tile.tileset; end
109
+ def type; @tile.type; end
110
+ def type=(value); @tile.type = value; end
111
+ def collision; @tile.collision; end
112
+ def collision=(value); @tile.collision = value; end
113
+ def collision_enable; @tile.collision_enable; end
114
+ def collision_enable=(value); @tile.collision_enable = value; end
115
+
116
+ def to_sprite(x, y)
117
+ TileObject.new(x, y, self, rotation: @angle)
118
+ end
119
+ end
120
+
121
+ module DiagonallyFlippedTile
122
+ def width ; @tile.height; end
123
+ def height; @tile.width ; end
124
+
125
+ def offset_x
126
+ @tile.offset_x + (@tile.height - @tile.width) / 2
127
+ end
128
+
129
+ def offset_y
130
+ @tile.offset_y + (@tile.height - @tile.width) / 2
131
+ end
132
+
133
+ def adjusted_offset_y
134
+ @tile.adjusted_offset_y + (@tile.height - @tile.width) / 2
135
+ end
136
+ end
137
+ end
138
+ end
139
+