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, #z

Instance Method Summary collapse

Methods included from Renderable

#add, #contains?, #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
# File 'lib/ruby2d/sprite.rb', line 10

def initialize(path, opts = {})
  # Sprite image file path
  @path = path

  # Initialize the sprite texture
  @texture = Texture.new(*Image.load_image(@path))
  @img_width = @texture.width
  @img_height = @texture.height

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

  # Flipping status
  @flip = nil

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

  # Dimensions
  @width  = opts[:width]  || nil
  @height = opts[:height] || nil

  # 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

#heightObject

Returns the value of attribute height.



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

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

#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

#widthObject

Returns the value of attribute width.



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

def width
  @width
end

#xObject

Returns the value of attribute x.



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

def x
  @x
end

#yObject

Returns the value of attribute y.



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

def y
  @y
end

Instance Method Details

#draw(opts = {}) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/ruby2d/sprite.rb', line 194

def draw(opts = {})
  Window.render_ready_check

  opts[:width] = opts[:width] || (@width || @clip_width)
  opts[:height] = opts[:height] || (@height || @clip_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

  render(x: opts[:x], y: opts[:y], width: opts[:width], height: opts[:height], color: Color.new(color), rotate: opts[:rotate], crop: {
    x: opts[:clip_x],
    y: opts[:clip_y],
    width: opts[:clip_width],
    height: opts[:clip_height],
    image_width: @img_width,
    image_height: @img_height,
  })
end

#elapsed_timeObject

Calculate the time in ms



155
156
157
# File 'lib/ruby2d/sprite.rb', line 155

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

#flip_sprite(flip) ⇒ Object

Flip the sprite



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/ruby2d/sprite.rb', line 117

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
end

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

Play an animation



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/ruby2d/sprite.rb', line 70

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



130
131
132
133
134
135
# File 'lib/ruby2d/sprite.rb', line 130

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



160
161
162
# File 'lib/ruby2d/sprite.rb', line 160

def restart_time
  @start_time = Time.now.to_f
end

#set_frameObject

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



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/ruby2d/sprite.rb', line 138

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



107
108
109
110
111
112
113
114
# File 'lib/ruby2d/sprite.rb', line 107

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`



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/ruby2d/sprite.rb', line 165

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
          # allow proc to make nested `play/do` calls to sequence multiple
          # animations by clearing `@done_proc` before the call
          kept_done_proc = @done_proc
          @done_proc = nil
          kept_done_proc.call
        end
      end
    end

    set_frame
  end
end