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.
@@ -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
+