Class: Ruby2D::Sprite

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

Instance Attribute Summary collapse

Attributes included from Renderable

#z

Instance Method Summary collapse

Methods included from Renderable

#a, #a=, #add, #b, #b=, #colour, #colour=, #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 = {})

  # Check if sprite file exists, unless running on the web
  unless RUBY_ENGINE == 'opal'
    unless File.exists? path
      raise Error, "Cannot find sprite image file `#{path}`"
    end
  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

  # 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
  ext_init(@path)

  # 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
  add
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

#heightObject

Returns the value of attribute height.



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

def height
  @height
end

#loopObject

Returns the value of attribute loop.



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

def loop
  @loop
end

#rotateObject

Returns the value of attribute rotate.



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

def rotate
  @rotate
end

#widthObject

Returns the value of attribute width.



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

def width
  @width
end

#xObject

Returns the value of attribute x.



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

def x
  @x
end

#yObject

Returns the value of attribute y.



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

def y
  @y
end

Instance Method Details

#elapsed_timeObject

Calculate the time in ms



206
207
208
# File 'lib/ruby2d/sprite.rb', line 206

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

#ext_init(path) ⇒ Object



172
173
174
# File 'ext/ruby2d/ruby2d-opal.rb', line 172

def ext_init(path)
  `#{self}.data = S2D.CreateSprite(path);`
end

#ext_renderObject



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'ext/ruby2d/ruby2d-opal.rb', line 176

def ext_render
  `
  #{self}.data.x = #{self}.x;
  #{self}.data.y = #{self}.y;

  S2D.ClipSprite(
    #{self}.data,
    #{self}.clip_x,
    #{self}.clip_y,
    #{self}.clip_w,
    #{self}.clip_h
  );

  S2D.DrawSprite(#{self}.data);
  `
end

#flip_sprite(flip) ⇒ Object

Flip the sprite



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/ruby2d/sprite.rb', line 152

def flip_sprite(flip)

  # A width and height must be set for the sprite for this to work
  unless @width && @height then return end

  @flip = flip

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

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

#play(animation = nil, loop = nil, flip = nil, &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
# File 'lib/ruby2d/sprite.rb', line 111

def play(animation = nil, loop = nil, flip = nil, &done_proc)
  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 == :loop || @defaults[:loop] ? true : false

    set_frame
    restart_time
  end
end

#reset_clipping_rectObject

Reset frame to defaults



181
182
183
184
185
186
# File 'lib/ruby2d/sprite.rb', line 181

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



211
212
213
# File 'lib/ruby2d/sprite.rb', line 211

def restart_time
  @start_time = Time.now.to_f
end

#set_frameObject

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



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/ruby2d/sprite.rb', line 189

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



142
143
144
145
146
147
148
149
# File 'lib/ruby2d/sprite.rb', line 142

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 ‘Sprite#ext_render`



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/ruby2d/sprite.rb', line 216

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