Class: Ruby2D::Sprite

Inherits:
Object
  • Object
show all
Includes:
Renderable
Defined in:
lib/ruby2d/sprite.rb

Instance Attribute Summary collapse

Attributes included from Renderable

#color, #height, #width, #x, #y, #z

Instance Method Summary collapse

Methods included from Renderable

#a, #a=, #add, #b, #b=, #contains?, #g, #g=, #opacity, #opacity=, #r, #r=, #remove

Constructor Details

#initialize(path, opts = {}) ⇒ Sprite

Returns a new instance of Sprite.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/ruby2d/sprite.rb', line 10

def initialize(path, opts = {})
  unless File.exist? path
    raise Error, "Cannot find sprite image file `#{path}`"
  end

  # Sprite image file path
  @path = path

  # Coordinates, size, and rotation of the sprite
  @x = opts[:x] || 0
  @y = opts[:y] || 0
  @z = opts[:z] || 0
  @width  = opts[:width]  || nil
  @height = opts[:height] || nil
  @rotate = opts[:rotate] || 0
  self.color = opts[:color] || 'white'
  self.opacity = opts[:opacity] if opts[:opacity]

  # Flipping status, coordinates, and size, used internally
  @flip = nil
  @flip_x = @x
  @flip_y = @y
  @flip_width  = @width
  @flip_height = @height

  # Animation attributes
  @start_time = 0.0
  @loop = opts[:loop] || false
  @frame_time = opts[:time] || 300
  @animations = opts[:animations] || {}
  @playing = false
  @current_frame = opts[:default] || 0
  @last_frame = 0
  @done_proc = nil

  # The sprite image size set by the native extension `ext_init`
  @img_width = nil; @img_height = nil

  # Initialize the sprite
  unless ext_init(@path)
    raise Error, "Sprite image `#{@path}` cannot be created"
  end

  # The clipping rectangle
  @clip_x = opts[:clip_x] || 0
  @clip_y = opts[:clip_y] || 0
  @clip_width  = opts[:clip_width]  || @img_width
  @clip_height = opts[:clip_height] || @img_height

  # Set the default animation
  @animations[:default] = 0..(@img_width / @clip_width) - 1

  # Set the sprite defaults
  @defaults = {
    animation:   @animations.first[0],
    frame:       @current_frame,
    frame_time:  @frame_time,
    clip_x:      @clip_x,
    clip_y:      @clip_y,
    clip_width:  @clip_width,
    clip_height: @clip_height,
    loop:        @loop
  }

  # Add the sprite to the window
  unless opts[:show] == false then add end
end

Instance Attribute Details

#clip_heightObject

Returns the value of attribute clip_height.



8
9
10
# File 'lib/ruby2d/sprite.rb', line 8

def clip_height
  @clip_height
end

#clip_widthObject

Returns the value of attribute clip_width.



8
9
10
# File 'lib/ruby2d/sprite.rb', line 8

def clip_width
  @clip_width
end

#clip_xObject

Returns the value of attribute clip_x.



8
9
10
# File 'lib/ruby2d/sprite.rb', line 8

def clip_x
  @clip_x
end

#clip_yObject

Returns the value of attribute clip_y.



8
9
10
# File 'lib/ruby2d/sprite.rb', line 8

def clip_y
  @clip_y
end

#dataObject

Returns the value of attribute data.



8
9
10
# File 'lib/ruby2d/sprite.rb', line 8

def data
  @data
end

#loopObject

Returns the value of attribute loop.



8
9
10
# File 'lib/ruby2d/sprite.rb', line 8

def loop
  @loop
end

#pathObject (readonly)

Returns the value of attribute path.



7
8
9
# File 'lib/ruby2d/sprite.rb', line 7

def path
  @path
end

#rotateObject

Returns the value of attribute rotate.



8
9
10
# File 'lib/ruby2d/sprite.rb', line 8

def rotate
  @rotate
end

Instance Method Details

#draw(opts = {}) ⇒ Object



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/ruby2d/sprite.rb', line 250

def draw(opts = {})
  opts[:width] = opts[:width] || @flip_width
  opts[:height] = opts[:height] || @flip_height
  opts[:rotate] = opts[:rotate] || @rotate
  opts[:clip_x] = opts[:clip_x] || @clip_x
  opts[:clip_y] = opts[:clip_y] || @clip_y
  opts[:clip_width] = opts[:clip_width] || @clip_width
  opts[:clip_height] = opts[:clip_height] || @clip_height
  unless opts[:color]
    opts[:color] = [1.0, 1.0, 1.0, 1.0]
  end

  self.class.ext_draw([
    self, opts[:x], opts[:y], opts[:width], opts[:height], opts[:rotate],
    opts[:clip_x], opts[:clip_y], opts[:clip_width], opts[:clip_height],
    opts[:color][0], opts[:color][1], opts[:color][2], opts[:color][3]
  ])
end

#elapsed_timeObject

Calculate the time in ms



216
217
218
# File 'lib/ruby2d/sprite.rb', line 216

def elapsed_time
  (Time.now.to_f - @start_time) * 1000
end

#flip_sprite(flip) ⇒ Object

Flip the sprite



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/ruby2d/sprite.rb', line 158

def flip_sprite(flip)

  # The sprite width and height must be set for it to be flipped correctly
  if (!@width || !@height) && flip
    raise Error,
     "Sprite width and height must be set in order to flip; " +
     "occured playing animation `:#{@playing_animation}` with image `#{@path}`"
  end

  @flip = flip

  # Reset flip values
  @flip_x      = @x
  @flip_y      = @y
  @flip_width  = @width
  @flip_height = @height

  case flip
  when :horizontal
    @flip_x      = @x + @width
    @flip_width  = -@width
  when :vertical
    @flip_y      = @y + @height
    @flip_height = -@height
  when :both     # horizontal and vertical
    @flip_x      = @x + @width
    @flip_width  = -@width
    @flip_y      = @y + @height
    @flip_height = -@height
  end
end

#height=(height) ⇒ Object

Set the height



103
104
105
106
107
108
# File 'lib/ruby2d/sprite.rb', line 103

def height=(height)
  @height = @flip_height = height
  if @flip == :vertical || @flip == :both
    @flip_height = -height
  end
end

#play(opts = {}, &done_proc) ⇒ Object

Play an animation



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/ruby2d/sprite.rb', line 111

def play(opts = {}, &done_proc)

  animation = opts[:animation]
  loop = opts[:loop]
  flip = opts[:flip]

  if !@playing || (animation != @playing_animation && animation != nil) || flip != @flip

    @playing = true
    @playing_animation = animation || :default
    frames = @animations[@playing_animation]
    flip_sprite(flip)
    @done_proc = done_proc

    case frames
    # When animation is a range, play through frames horizontally
    when Range
      @first_frame   = frames.first || @defaults[:frame]
      @current_frame = frames.first || @defaults[:frame]
      @last_frame    = frames.last
    # When array...
    when Array
      @first_frame   = 0
      @current_frame = 0
      @last_frame    = frames.length - 1
    end

    # Set looping
    @loop = loop == true || @defaults[:loop] ? true : false

    set_frame
    restart_time
  end
  self
end

#reset_clipping_rectObject

Reset frame to defaults



191
192
193
194
195
196
# File 'lib/ruby2d/sprite.rb', line 191

def reset_clipping_rect
  @clip_x      = @defaults[:clip_x]
  @clip_y      = @defaults[:clip_y]
  @clip_width  = @defaults[:clip_width]
  @clip_height = @defaults[:clip_height]
end

#restart_timeObject

Restart the timer



221
222
223
# File 'lib/ruby2d/sprite.rb', line 221

def restart_time
  @start_time = Time.now.to_f
end

#set_frameObject

Set the position of the clipping retangle based on the current frame



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/ruby2d/sprite.rb', line 199

def set_frame
  frames = @animations[@playing_animation]
  case frames
  when Range
    reset_clipping_rect
    @clip_x = @current_frame * @clip_width
  when Array
    f = frames[@current_frame]
    @clip_x      = f[:x]      || @defaults[:clip_x]
    @clip_y      = f[:y]      || @defaults[:clip_y]
    @clip_width  = f[:width]  || @defaults[:clip_width]
    @clip_height = f[:height] || @defaults[:clip_height]
    @frame_time  = f[:time]   || @defaults[:frame_time]
  end
end

#stop(animation = nil) ⇒ Object

Stop the current animation and set to the default frame



148
149
150
151
152
153
154
155
# File 'lib/ruby2d/sprite.rb', line 148

def stop(animation = nil)
  if !animation || animation == @playing_animation
    @playing = false
    @playing_animation = @defaults[:animation]
    @current_frame = @defaults[:frame]
    set_frame
  end
end

#updateObject

Update the sprite animation, called by ‘render`



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/ruby2d/sprite.rb', line 226

def update
  if @playing

    # Advance the frame
    unless elapsed_time <= (@frame_time || @defaults[:frame_time])
      @current_frame += 1
      restart_time
    end

    # Reset to the starting frame if all frames played
    if @current_frame > @last_frame
      @current_frame = @first_frame
      unless @loop
        # Stop animation and play block, if provided
        stop
        if @done_proc then @done_proc.call end
        @done_proc = nil
      end
    end

    set_frame
  end
end

#width=(width) ⇒ Object

Set the width



95
96
97
98
99
100
# File 'lib/ruby2d/sprite.rb', line 95

def width=(width)
  @width = @flip_width = width
  if @flip == :horizontal || @flip == :both
    @flip_width = -width
  end
end

#x=(x) ⇒ Object

Set the x coordinate



79
80
81
82
83
84
# File 'lib/ruby2d/sprite.rb', line 79

def x=(x)
  @x = @flip_x = x
  if @flip == :horizontal || @flip == :both
    @flip_x = x + @width
  end
end

#y=(y) ⇒ Object

Set the y coordinate



87
88
89
90
91
92
# File 'lib/ruby2d/sprite.rb', line 87

def y=(y)
  @y = @flip_y = y
  if @flip == :vertical || @flip == :both
    @flip_y = y + @height
  end
end