diff options
| author | Tom Black <[email protected]> | 2018-01-30 00:23:34 -0800 |
|---|---|---|
| committer | Tom Black <[email protected]> | 2018-05-06 15:41:06 -0700 |
| commit | 7d3cff5e5d6d53d7f4def94a9dc831e099e03e67 (patch) | |
| tree | c3fc81f0ee676208dee1530ff5935f1b88692677 /lib | |
| parent | 2e07255723428d09eab38ad1a5fde11fc9a287d8 (diff) | |
| download | ruby2d-7d3cff5e5d6d53d7f4def94a9dc831e099e03e67.tar.gz ruby2d-7d3cff5e5d6d53d7f4def94a9dc831e099e03e67.zip | |
Sprite class redesign
See #33 for discussion
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/ruby2d/sprite.rb | 171 |
1 files changed, 107 insertions, 64 deletions
diff --git a/lib/ruby2d/sprite.rb b/lib/ruby2d/sprite.rb index 7c66f97..a9d9e98 100644 --- a/lib/ruby2d/sprite.rb +++ b/lib/ruby2d/sprite.rb @@ -2,11 +2,12 @@ module Ruby2D class Sprite + include Renderable - attr_accessor :x, :y, :clip_x, :clip_y, :clip_w, :clip_h, :data - attr_reader :z + attr_accessor :x, :y, :width, :height, :loop, + :clip_x, :clip_y, :clip_width, :clip_height, :data - def initialize(x, y, path, z=0) + def initialize(path, opts = {}) unless RUBY_ENGINE == 'opal' unless File.exists? path @@ -14,88 +15,130 @@ module Ruby2D end end - @x, @y, @path = x, y, path - @clip_x, @clip_y, @clip_w, @clip_h = 0, 0, 0, 0 - @default = nil - @animations = {} - @current_animation = nil - @current_frame = 0 - @current_frame_time = 0 - @z = z - - ext_init(path) - if Module.const_defined? :DSL - Application.add(self) - end + @path = path + @x = opts[:x] || 0 + @y = opts[:y] || 0 + @z = opts[:z] || 0 + @width = opts[:width] || nil + @height = opts[:height] || nil + @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 + + ext_init(@path) + @clip_x = opts[:clip_x] || 0 + @clip_y = opts[:clip_y] || 0 + @clip_width = opts[:clip_width] || @width + @clip_height = opts[:clip_height] || @height + @animations[:default] = 0..(@width / @clip_width) - 1 # set default animation + + @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 end - def start(x, y, w, h) - @default = [x, y, w, h] - clip(x, y, w, h) - end + def play(animation = nil, loop = nil) + if !@playing || (animation != @playing_animation && animation != nil) + + @playing = true + @playing_animation = animation || :default + frames = @animations[@playing_animation] + + 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 - def add(animations) - @animations.merge!(animations) - end + # Set looping + @loop = loop == :loop || @defaults[:loop] ? true : false - def animate(animation) - if @current_animation != animation - @current_frame = 0 - @current_frame_time = 0 - @current_animation = animation + set_frame + restart_time end - animate_frames(@animations[animation]) end - def reset - clip(@default[0], @default[1], @default[2], @default[3]) - @current_animation = nil + # Stop the current animation and set to the default frame + def stop + @playing = false + @playing_animation = @defaults[:animation] + @current_frame = @defaults[:frame] + set_frame end - # TODO: Sprite already has an `add` method, have to reconsile - # def add - # if Module.const_defined? :DSL - # Application.add(self) - # end - # end + # Reset frame to defaults + 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 - def remove - if Module.const_defined? :DSL - Application.remove(self) + # Set the position of the clipping retangle based on the current frame + 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 - def width - @current_animation ? @animations[@current_animation][@current_frame][2] : @default[2] + # Calculate the time in ms + def elapsed_time + (Time.now.to_f - @start_time) * 1000 end - def height - @current_animation ? @animations[@current_animation][@current_frame][3] : @default[3] + # Restart the timer + def restart_time + @start_time = Time.now.to_f end - private + # Update the sprite animation, called by `Sprite#ext_render` + def update + if @playing - def clip(x, y, w, h) - @clip_x, @clip_y, @clip_w, @clip_h = x, y, w, h - end + # Advance the frame + unless elapsed_time <= (@frame_time || @defaults[:frame_time]) + @current_frame += 1 + restart_time + end - def animate_frames(frames) - if @current_frame_time < frames[@current_frame][4] - clip_with_current_frame(frames) - @current_frame_time += 1 - else - @current_frame += 1 - if @current_frame == frames.length - @current_frame = 0 + # Reset to the starting frame if all frames played + if @current_frame > @last_frame + @current_frame = @first_frame + unless @loop then stop end end - clip_with_current_frame(frames) - @current_frame_time = 0 - end - end - def clip_with_current_frame(frames) - clip(frames[@current_frame][0], frames[@current_frame][1], - frames[@current_frame][2], frames[@current_frame][3]) + set_frame + end end end |
