ruby2d 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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