ruby2d 0.5.1 → 0.6.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.
@@ -1,36 +1,39 @@
1
- # dsl.rb
1
+ # Ruby2D::DSL
2
2
 
3
3
  module Ruby2D::DSL
4
+
5
+ Ruby2D::Window.new
6
+
4
7
  def get(sym)
5
- Application.get(sym)
8
+ Window.get(sym)
6
9
  end
7
10
 
8
11
  def set(opts)
9
- Application.set(opts)
12
+ Window.set(opts)
10
13
  end
11
14
 
12
15
  def on(event, &proc)
13
- Application.on(event, &proc)
16
+ Window.on(event, &proc)
14
17
  end
15
18
 
16
19
  def off(event_descriptor)
17
- Application.off(event_descriptor)
20
+ Window.off(event_descriptor)
18
21
  end
19
22
 
20
23
  def update(&proc)
21
- Application.update(&proc)
24
+ Window.update(&proc)
22
25
  end
23
26
 
24
27
  def clear
25
- Application.clear
28
+ Window.clear
26
29
  end
27
30
 
28
31
  def show
29
- Application.show
32
+ Window.show
30
33
  end
31
34
 
32
35
  def close
33
- Application.close
36
+ Window.close
34
37
  end
35
38
 
36
39
  end
@@ -1,4 +1,4 @@
1
- # exceptions.rb
1
+ # Ruby2D::Error
2
2
 
3
3
  module Ruby2D
4
4
  class Error < StandardError
@@ -1,11 +1,11 @@
1
- # image.rb
1
+ # Ruby2D::Image
2
2
 
3
3
  module Ruby2D
4
4
  class Image
5
5
  include Renderable
6
6
 
7
- attr_accessor :x, :y, :width, :height, :data
8
7
  attr_reader :path, :color
8
+ attr_accessor :x, :y, :width, :height, :rotate, :data
9
9
 
10
10
  def initialize(opts = {})
11
11
  @path = opts[:path]
@@ -19,9 +19,9 @@ module Ruby2D
19
19
  @x = opts[:x] || 0
20
20
  @y = opts[:y] || 0
21
21
  @z = opts[:z] || 0
22
- @width = opts[:width] || nil
22
+ @width = opts[:width] || nil
23
23
  @height = opts[:height] || nil
24
-
24
+ @rotate = opts[:rotate] || 0
25
25
  self.color = opts[:color] || 'white'
26
26
 
27
27
  ext_init(@path)
@@ -35,5 +35,6 @@ module Ruby2D
35
35
  def contains?(x, y)
36
36
  @x < x and @x + @width > x and @y < y and @y + @height > y
37
37
  end
38
+
38
39
  end
39
40
  end
@@ -1,8 +1,9 @@
1
- # line.rb
1
+ # Ruby2D::Line
2
2
 
3
3
  module Ruby2D
4
4
  class Line
5
5
  include Renderable
6
+
6
7
  attr_accessor :x1, :x2, :y1, :y2, :color, :width
7
8
 
8
9
  def initialize(opts = {})
@@ -13,7 +14,6 @@ module Ruby2D
13
14
  @width = opts[:width] || 2
14
15
  @z = opts[:z] || 0
15
16
  self.color = opts[:color] || 'white'
16
-
17
17
  add
18
18
  end
19
19
 
@@ -22,13 +22,15 @@ module Ruby2D
22
22
  update_color(@color)
23
23
  end
24
24
 
25
+ # Return the length of the line
25
26
  def length
26
27
  points_distance(@x1, @y1, @x2, @y2)
27
28
  end
28
29
 
29
- # Line contains a point if the point is closer than the length of line from both ends
30
- # and if the distance from point to line is smaller than half of the width.
31
- # Check https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line for reference
30
+ # Line contains a point if the point is closer than the length of line from
31
+ # both ends and if the distance from point to line is smaller than half of
32
+ # the width. For reference:
33
+ # https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
32
34
  def contains?(x, y)
33
35
  points_distance(x1, y1, x, y) < length and
34
36
  points_distance(x2, y2, x, y) < length and
@@ -37,6 +39,7 @@ module Ruby2D
37
39
 
38
40
  private
39
41
 
42
+ # Calculate the distance between two points
40
43
  def points_distance(x1, y1, x2, y2)
41
44
  Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
42
45
  end
@@ -58,5 +61,6 @@ module Ruby2D
58
61
  @c4 = c
59
62
  end
60
63
  end
64
+
61
65
  end
62
66
  end
@@ -1,10 +1,10 @@
1
- # music.rb
1
+ # Ruby2D::Music
2
2
 
3
3
  module Ruby2D
4
4
  class Music
5
5
 
6
- attr_accessor :data, :loop
7
6
  attr_reader :path
7
+ attr_accessor :loop, :data
8
8
 
9
9
  def initialize(path)
10
10
 
@@ -19,24 +19,30 @@ module Ruby2D
19
19
  ext_init(path)
20
20
  end
21
21
 
22
+ # Play the music
22
23
  def play
23
24
  ext_play
24
25
  end
25
26
 
27
+ # Pause the music
26
28
  def pause
27
29
  ext_pause
28
30
  end
29
31
 
32
+ # Resume paused music
30
33
  def resume
31
34
  ext_resume
32
35
  end
33
36
 
37
+ # Stop playing the music, start at beginning
34
38
  def stop
35
39
  ext_stop
36
40
  end
37
41
 
42
+ # Fade out music over provided milliseconds
38
43
  def fadeout(ms)
39
44
  ext_fadeout(ms)
40
45
  end
46
+
41
47
  end
42
48
  end
@@ -1,8 +1,11 @@
1
- # quad.rb
1
+ # Ruby2D::Quad
2
2
 
3
3
  module Ruby2D
4
4
  class Quad
5
5
  include Renderable
6
+
7
+ attr_reader :color
8
+
6
9
  # Coordinates in clockwise order, starting at top left:
7
10
  # x1,y1 == top left
8
11
  # x2,y2 == top right
@@ -13,8 +16,6 @@ module Ruby2D
13
16
  :x3, :y3, :c3,
14
17
  :x4, :y4, :c4
15
18
 
16
- attr_reader :color
17
-
18
19
  def initialize(opts = {})
19
20
  @x1 = opts[:x1] || 0
20
21
  @y1 = opts[:y1] || 0
@@ -24,9 +25,7 @@ module Ruby2D
24
25
  @y3 = opts[:y3] || 100
25
26
  @x4 = opts[:x4] || 0
26
27
  @y4 = opts[:y4] || 100
27
-
28
- @z = opts[:z] || 0
29
-
28
+ @z = opts[:z] || 0
30
29
  self.color = opts[:color] || 'white'
31
30
  add
32
31
  end
@@ -73,5 +72,6 @@ module Ruby2D
73
72
  @c4 = c
74
73
  end
75
74
  end
75
+
76
76
  end
77
77
  end
@@ -1,4 +1,4 @@
1
- # rectangle.rb
1
+ # Ruby2D::Rectangle
2
2
 
3
3
  module Ruby2D
4
4
  class Rectangle < Quad
@@ -6,15 +6,13 @@ module Ruby2D
6
6
  attr_reader :x, :y, :width, :height
7
7
 
8
8
  def initialize(opts = {})
9
- @x = opts[:x] || 0
10
- @y = opts[:y] || 0
11
- @z = opts[:z] || 0
12
- @width = opts[:width] || 200
9
+ @x = opts[:x] || 0
10
+ @y = opts[:y] || 0
11
+ @z = opts[:z] || 0
12
+ @width = opts[:width] || 200
13
13
  @height = opts[:height] || 100
14
-
15
- update_coords(@x, @y, @width, @height)
16
-
17
14
  self.color = opts[:color] || 'white'
15
+ update_coords(@x, @y, @width, @height)
18
16
  add
19
17
  end
20
18
 
@@ -1,35 +1,51 @@
1
+ # Ruby2D::Renderable
2
+
1
3
  module Ruby2D
2
4
  module Renderable
5
+
3
6
  attr_reader :z
4
7
 
8
+ # Set the z position (depth) of the object
5
9
  def z=(z)
6
10
  remove
7
11
  @z = z
8
12
  add
9
13
  end
10
14
 
15
+ # Add the object to the window
11
16
  def add
12
17
  if Module.const_defined? :DSL
13
- Application.add(self)
18
+ Window.add(self)
14
19
  end
15
20
  end
16
21
 
22
+ # Remove the object from the window
17
23
  def remove
18
24
  if Module.const_defined? :DSL
19
- Application.remove(self)
25
+ Window.remove(self)
20
26
  end
21
27
  end
22
28
 
23
- def opacity
24
- self.color.opacity
25
- end
29
+ # Allow shortcuts for setting color values
30
+ def r; self.color.r end
31
+ def g; self.color.g end
32
+ def b; self.color.b end
33
+ def a; self.color.a end
34
+ def r=(c); self.color.r = c end
35
+ def g=(c); self.color.g = c end
36
+ def b=(c); self.color.b = c end
37
+ def a=(c); self.color.a = c end
38
+ def opacity; self.color.opacity end
39
+ def opacity=(val); self.color.opacity = val end
26
40
 
27
- def opacity=(val)
28
- self.color.opacity = val
29
- end
41
+ # Allow British English spelling of color
42
+ def colour; self.color end
43
+ def colour=(c); self.color = c end
30
44
 
45
+ # Add a contains method stub
31
46
  def contains?(x, y)
32
- raise "Not implemented yet"
47
+ raise Error, "\`#contains?\` not implemented for this class yet"
33
48
  end
49
+
34
50
  end
35
51
  end
@@ -1,10 +1,10 @@
1
- # sound.rb
1
+ # Ruby2D::Sound
2
2
 
3
3
  module Ruby2D
4
4
  class Sound
5
5
 
6
- attr_accessor :data
7
6
  attr_reader :path
7
+ attr_accessor :data
8
8
 
9
9
  def initialize(path)
10
10
 
@@ -18,6 +18,7 @@ module Ruby2D
18
18
  ext_init(path)
19
19
  end
20
20
 
21
+ # Play the sound
21
22
  def play
22
23
  ext_play
23
24
  end
@@ -1,101 +1,240 @@
1
- # sprite.rb
1
+ # Ruby2D::Sprite
2
2
 
3
3
  module Ruby2D
4
4
  class Sprite
5
+ include Renderable
5
6
 
6
- attr_accessor :x, :y, :clip_x, :clip_y, :clip_w, :clip_h, :data
7
- attr_reader :z
7
+ attr_reader :x, :y, :width, :height
8
+ attr_accessor :rotate, :loop, :clip_x, :clip_y, :clip_width, :clip_height, :data
8
9
 
9
- def initialize(x, y, path, z=0)
10
+ def initialize(path, opts = {})
10
11
 
12
+ # Check if sprite file exists, unless running on the web
11
13
  unless RUBY_ENGINE == 'opal'
12
14
  unless File.exists? path
13
15
  raise Error, "Cannot find sprite image file `#{path}`"
14
16
  end
15
17
  end
16
18
 
17
- @x, @y, @path = x, y, path
18
- @clip_x, @clip_y, @clip_w, @clip_h = 0, 0, 0, 0
19
- @default = nil
20
- @animations = {}
21
- @current_animation = nil
22
- @current_frame = 0
23
- @current_frame_time = 0
24
- @z = z
25
-
26
- ext_init(path)
27
- if Module.const_defined? :DSL
28
- Application.add(self)
19
+ # Sprite image file path
20
+ @path = path
21
+
22
+ # Coordinates, size, and rotation of the sprite
23
+ @x = opts[:x] || 0
24
+ @y = opts[:y] || 0
25
+ @z = opts[:z] || 0
26
+ @width = opts[:width] || nil
27
+ @height = opts[:height] || nil
28
+ @rotate = opts[:rotate] || 0
29
+
30
+ # Flipping status, coordinates, and size, used internally
31
+ @flip = nil
32
+ @flip_x = @x
33
+ @flip_y = @y
34
+ @flip_width = @width
35
+ @flip_height = @height
36
+
37
+ # Animation attributes
38
+ @start_time = 0.0
39
+ @loop = opts[:loop] || false
40
+ @frame_time = opts[:time] || 300
41
+ @animations = opts[:animations] || {}
42
+ @playing = false
43
+ @current_frame = opts[:default] || 0
44
+ @last_frame = 0
45
+ @done_proc = nil
46
+
47
+ # The sprite image size set by the native extension `ext_init()`
48
+ @img_width = nil; @img_height = nil
49
+
50
+ # Initialize the sprite
51
+ ext_init(@path)
52
+
53
+ # The clipping rectangle
54
+ @clip_x = opts[:clip_x] || 0
55
+ @clip_y = opts[:clip_y] || 0
56
+ @clip_width = opts[:clip_width] || @img_width
57
+ @clip_height = opts[:clip_height] || @img_height
58
+
59
+ # Set the default animation
60
+ @animations[:default] = 0..(@img_width / @clip_width) - 1
61
+
62
+ # Set the sprite defaults
63
+ @defaults = {
64
+ animation: @animations.first[0],
65
+ frame: @current_frame,
66
+ frame_time: @frame_time,
67
+ clip_x: @clip_x,
68
+ clip_y: @clip_y,
69
+ clip_width: @clip_width,
70
+ clip_height: @clip_height,
71
+ loop: @loop
72
+ }
73
+
74
+ # Add the sprite to the window
75
+ add
76
+ end
77
+
78
+ # Set the x coordinate
79
+ def x=(x)
80
+ @x = @flip_x = x
81
+ if @flip == :flip_h || @flip == :flip_hv
82
+ @flip_x = x + @width
29
83
  end
30
84
  end
31
85
 
32
- def start(x, y, w, h)
33
- @default = [x, y, w, h]
34
- clip(x, y, w, h)
86
+ # Set the y coordinate
87
+ def y=(y)
88
+ @y = @flip_y = y
89
+ if @flip == :flip_v || @flip == :flip_hv
90
+ @flip_y = y + @height
91
+ end
35
92
  end
36
93
 
37
- def add(animations)
38
- @animations.merge!(animations)
94
+ # Set the width
95
+ def width=(width)
96
+ @width = @flip_width = width
97
+ if @flip == :flip_h || @flip == :flip_hv
98
+ @flip_width = -width
99
+ end
39
100
  end
40
101
 
41
- def animate(animation)
42
- if @current_animation != animation
43
- @current_frame = 0
44
- @current_frame_time = 0
45
- @current_animation = animation
102
+ # Set the height
103
+ def height=(height)
104
+ @height = @flip_height = height
105
+ if @flip == :flip_v || @flip == :flip_hv
106
+ @flip_height = -height
46
107
  end
47
- animate_frames(@animations[animation])
48
108
  end
49
109
 
50
- def reset
51
- clip(@default[0], @default[1], @default[2], @default[3])
52
- @current_animation = nil
110
+ # Play an animation
111
+ def play(animation = nil, loop = nil, flip = nil, &done_proc)
112
+ if !@playing || (animation != @playing_animation && animation != nil) || flip != @flip
113
+
114
+ @playing = true
115
+ @playing_animation = animation || :default
116
+ frames = @animations[@playing_animation]
117
+ flip_sprite(flip)
118
+ @done_proc = done_proc
119
+
120
+ case frames
121
+ # When animation is a range, play through frames horizontally
122
+ when Range
123
+ @first_frame = frames.first || @defaults[:frame]
124
+ @current_frame = frames.first || @defaults[:frame]
125
+ @last_frame = frames.last
126
+ # When array...
127
+ when Array
128
+ @first_frame = 0
129
+ @current_frame = 0
130
+ @last_frame = frames.length - 1
131
+ end
132
+
133
+ # Set looping
134
+ @loop = loop == :loop || @defaults[:loop] ? true : false
135
+
136
+ set_frame
137
+ restart_time
138
+ end
53
139
  end
54
140
 
55
- # TODO: Sprite already has an `add` method, have to reconsile
56
- # def add
57
- # if Module.const_defined? :DSL
58
- # Application.add(self)
59
- # end
60
- # end
141
+ # Stop the current animation and set to the default frame
142
+ def stop(animation = nil)
143
+ if !animation || animation == @playing_animation
144
+ @playing = false
145
+ @playing_animation = @defaults[:animation]
146
+ @current_frame = @defaults[:frame]
147
+ set_frame
148
+ end
149
+ end
61
150
 
62
- def remove
63
- if Module.const_defined? :DSL
64
- Application.remove(self)
151
+ # Flip the sprite
152
+ def flip_sprite(flip)
153
+
154
+ # A width and height must be set for the sprite for this to work
155
+ unless @width && @height then return end
156
+
157
+ @flip = flip
158
+
159
+ # Reset flip values
160
+ @flip_x = @x
161
+ @flip_y = @y
162
+ @flip_width = @width
163
+ @flip_height = @height
164
+
165
+ case flip
166
+ when :flip_h # horizontal
167
+ @flip_x = @x + @width
168
+ @flip_width = -@width
169
+ when :flip_v # vertical
170
+ @flip_y = @y + @height
171
+ @flip_height = -@height
172
+ when :flip_hv # horizontal and vertical
173
+ @flip_x = @x + @width
174
+ @flip_width = -@width
175
+ @flip_y = @y + @height
176
+ @flip_height = -@height
65
177
  end
66
178
  end
67
179
 
68
- def width
69
- @current_animation ? @animations[@current_animation][@current_frame][2] : @default[2]
180
+ # Reset frame to defaults
181
+ def reset_clipping_rect
182
+ @clip_x = @defaults[:clip_x]
183
+ @clip_y = @defaults[:clip_y]
184
+ @clip_width = @defaults[:clip_width]
185
+ @clip_height = @defaults[:clip_height]
70
186
  end
71
187
 
72
- def height
73
- @current_animation ? @animations[@current_animation][@current_frame][3] : @default[3]
188
+ # Set the position of the clipping retangle based on the current frame
189
+ def set_frame
190
+ frames = @animations[@playing_animation]
191
+ case frames
192
+ when Range
193
+ reset_clipping_rect
194
+ @clip_x = @current_frame * @clip_width
195
+ when Array
196
+ f = frames[@current_frame]
197
+ @clip_x = f[:x] || @defaults[:clip_x]
198
+ @clip_y = f[:y] || @defaults[:clip_y]
199
+ @clip_width = f[:width] || @defaults[:clip_width]
200
+ @clip_height = f[:height] || @defaults[:clip_height]
201
+ @frame_time = f[:time] || @defaults[:frame_time]
202
+ end
74
203
  end
75
204
 
76
- private
205
+ # Calculate the time in ms
206
+ def elapsed_time
207
+ (Time.now.to_f - @start_time) * 1000
208
+ end
77
209
 
78
- def clip(x, y, w, h)
79
- @clip_x, @clip_y, @clip_w, @clip_h = x, y, w, h
210
+ # Restart the timer
211
+ def restart_time
212
+ @start_time = Time.now.to_f
80
213
  end
81
214
 
82
- def animate_frames(frames)
83
- if @current_frame_time < frames[@current_frame][4]
84
- clip_with_current_frame(frames)
85
- @current_frame_time += 1
86
- else
87
- @current_frame += 1
88
- if @current_frame == frames.length
89
- @current_frame = 0
215
+ # Update the sprite animation, called by `Sprite#ext_render`
216
+ def update
217
+ if @playing
218
+
219
+ # Advance the frame
220
+ unless elapsed_time <= (@frame_time || @defaults[:frame_time])
221
+ @current_frame += 1
222
+ restart_time
90
223
  end
91
- clip_with_current_frame(frames)
92
- @current_frame_time = 0
93
- end
94
- end
95
224
 
96
- def clip_with_current_frame(frames)
97
- clip(frames[@current_frame][0], frames[@current_frame][1],
98
- frames[@current_frame][2], frames[@current_frame][3])
225
+ # Reset to the starting frame if all frames played
226
+ if @current_frame > @last_frame
227
+ @current_frame = @first_frame
228
+ unless @loop
229
+ # Stop animation and play block, if provided
230
+ stop
231
+ if @done_proc then @done_proc.call end
232
+ @done_proc = nil
233
+ end
234
+ end
235
+
236
+ set_frame
237
+ end
99
238
  end
100
239
 
101
240
  end