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=, #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 = {})
  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
  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

#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

#elapsed_timeObject

Calculate the time in ms



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

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

#flip_sprite(flip) ⇒ Object

Flip the sprite



157
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
# File 'lib/ruby2d/sprite.rb', line 157

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

#reset_clipping_rectObject

Reset frame to defaults



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

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



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

def restart_time
  @start_time = Time.now.to_f
end

#set_frameObject

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



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

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



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

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`



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

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