#============================================================================== # ** Multiple Simultaneous Animations #----------------------------------------------------------------------------------------------------------------------------------------- # A sprite class with animation display processing added. # Made by Cuauhtemoc # Terms of use: Credit me # NOT compatible with Yanfly's Melody Engine. #============================================================================== class Sprite_Base < Sprite #-------------------------------------------------------------------------- # * Class Variable #-------------------------------------------------------------------------- @@animations = [] @@_reference_count = {} #-------------------------------------------------------------------------- # * Object Initialization # viewport : viewport #-------------------------------------------------------------------------- def initialize(viewport = nil) super(viewport) @animation = {} @use_sprite = true # Sprite use flag end #-------------------------------------------------------------------------- # * Dispose #-------------------------------------------------------------------------- def dispose super dispose_everything end #-------------------------------------------------------------------------- # * Frame Update #-------------------------------------------------------------------------- def update super if @animation.size > 0 @animation.each_value{ |animation| animation[16] -= 1 update_animation(animation) } end end #-------------------------------------------------------------------------- # * Determine if animation is being displayed #-------------------------------------------------------------------------- def animation? return @animation.size > 0 end #-------------------------------------------------------------------------- # * Start Animation #-------------------------------------------------------------------------- def start_animation(animation, mirror = false, loop = nil) animation_data = [] return if animation == nil if @animation.has_key?(animation.name) temp = @animation[animation.name] return if temp[15] @animation[animation.name][16] = temp[17] return end animation_data[0] = animation animation_data[1] = mirror animation_data[2] = animation.frame_max * 3 + 1 animation_data = load_animation_bitmap(animation_data) animation_sprites = [] if animation.position != 3 if @use_sprite for i in 0..15 sprite = ::Sprite.new(viewport) sprite.visible = false animation_sprites.push(sprite) end end end animation_data[3] = animation_sprites if animation_data[0].position == 3 if viewport == nil animation_data[4] = Graphics.width / 2 animation_data[5] = Graphics.height / 2 else animation_data[4] = viewport.rect.width / 2 animation_data[5] = viewport.rect.height / 2 end else animation_data[4] = x - ox + width / 2 animation_data[5] = y - oy + height / 2 if animation_data[0].position == 0 animation_data[5] -= height / 2 elsif animation_data[0].position == 2 animation_data[5] += height / 2 end end if loop != nil animation_data[15] = true if loop == animation.name end @animation[animation.name] = animation_data end #-------------------------------------------------------------------------- # * Read (Load) Animation Graphics #-------------------------------------------------------------------------- def load_animation_bitmap(animation_data) animation = animation_data[0] animation_data[6] = animation.animation1_name animation_data[7] = animation.animation1_hue animation_data[8] = animation.animation2_name animation_data[9] = animation.animation2_hue if animation_data[6].include?("Anim") animation_data[10] = true animation_data[12] = Cache.animation(animation_data[6], animation_data[7]).dup else animation_data[10] = false animation_data[12] = Cache.animation(animation_data[6], animation_data[7]) end if animation_data[8].include?("Anim") animation_data[11] = true animation_data[13] = Cache.animation(animation_data[8], animation_data[9]).dup else animation_data[11] = false animation_data[13] = Cache.animation(animation_data[8], animation_data[9]) end if animation_data[10] or animation_data[11] animation_data[16] = animation_data[0].frame_max * 2 + 1 animation_data[17] = animation_data[0].frame_max * 2 + 1 animation_data[14] = 2 else animation_data[16] = animation_data[0].frame_max * 3 + 1 animation_data[17] = animation_data[0].frame_max * 3 + 1 animation_data[14] = 3 end Graphics.frame_reset return animation_data end #-------------------------------------------------------------------------- # * Dispose of Animation #-------------------------------------------------------------------------- def dispose_animation(animation) if animation.is_a?(Array) name = animation[0].name if animation[12] != nil animation[12].dispose Cache.free(animation[0].animation1_name) if !animation[10] end if animation[13] != nil animation[13].dispose Cache.free(animation[0].animation2_name) if !animation[11] end if animation[3] != nil for sprite in animation[3] sprite.dispose end animation[3] = nil animation[0] = nil end animation[12] = nil animation[13] = nil elsif animation.is_a?(RPG::Animation) dispose_animation(@animation[animation.name]) return end return name end #-------------------------------------------------------------------------- # * Disposes of every animation stored in the animation hash #-------------------------------------------------------------------------- def dispose_everything return if @animation == nil @animation.each_pair{ |key, animation| if animation[3] != nil for sprite in animation[3] sprite.dispose end animation[3] = nil end if animation[12] != nil animation[12].dispose Cache.free(animation[0].animation1_name) if !animation[10] end if animation[13] != nil animation[13].dispose Cache.free(animation[0].animation2_name) if !animation[11] end animation[0] = nil @animation[key] = nil } @animation.clear GC.start @animation = nil end #-------------------------------------------------------------------------- # * Stops a looping animation from looping again #-------------------------------------------------------------------------- def stop_loop(name) if @animation.has_key?(name) animation = @animation[name] animation[15] = false animation[17] = animation[0].frame_max * 2 + 1 @animation[name] = animation end end #-------------------------------------------------------------------------- # * Update Animation #-------------------------------------------------------------------------- def update_animation(animation) if animation[15] if animation[16] > 0 frame_index = animation[0].frame_max - (animation[16] + animation[14] - 1) / animation[14] animation_set_sprites(animation[0].frames[frame_index], animation) if animation[16] % animation[14] == 0 for timing in animation[0].timings next unless timing.frame == frame_index animation_process_timing(timing, animation[14]) end end elsif animation[16] <= 0 animation[16] = animation[17] end elsif animation[16] > 0 frame_index = animation[0].frame_max - (animation[16] + animation[14] - 1) / animation[14] animation_set_sprites(animation[0].frames[frame_index], animation) if animation[16] % animation[14] == 0 for timing in animation[0].timings next unless timing.frame == frame_index animation_process_timing(timing, animation[14]) end end else @animation.delete(dispose_animation(animation)) end end #-------------------------------------------------------------------------- # * Set Animation Sprite # frame : Frame data (RPG::Animation::Frame) #-------------------------------------------------------------------------- def animation_set_sprites(frame, animation) cell_data = frame.cell_data for i in 0..15 sprite = animation[3][i] next if sprite == nil pattern = cell_data[i, 0] if pattern == nil or pattern == -1 sprite.visible = false next end if pattern < 100 sprite.bitmap = animation[12] else sprite.bitmap = animation[13] end sprite.visible = true if animation[10] and (sprite.bitmap == animation[12]) anim_height = 240 anim_width = animation[12].width / 5 elsif animation[11] and (sprite.bitmap == animation[13]) anim_height = 240 anim_width = animation[13].width / 5 else anim_height = 192 anim_width = 192 end sprite.src_rect.set(pattern % 5 * anim_width, pattern % 100 / 5 * anim_height, anim_width, anim_height) if animation[1] sprite.x = animation[4] - cell_data[i, 1] sprite.y = animation[5] + cell_data[i, 2] sprite.angle = (360 - cell_data[i, 4]) sprite.mirror = (cell_data[i, 5] == 0) else sprite.x = animation[4] + cell_data[i, 1] sprite.y = animation[5] + cell_data[i, 2] sprite.angle = cell_data[i, 4] sprite.mirror = (cell_data[i, 5] == 1) end sprite.z = self.z + 300 + i sprite.ox = anim_width / 2 sprite.oy = anim_height / 2 sprite.zoom_x = cell_data[i, 3] / 100.0 sprite.zoom_y = cell_data[i, 3] / 100.0 sprite.opacity = cell_data[i, 6] * self.opacity / 255.0 sprite.blend_type = cell_data[i, 7] end end #-------------------------------------------------------------------------- # * SE and Flash Timing Processing # timing : timing data (RPG::Animation::Timing) #-------------------------------------------------------------------------- def animation_process_timing(timing, rate) timing.se.play case timing.flash_scope when 1 self.flash(timing.flash_color, timing.flash_duration * rate) when 2 if viewport != nil viewport.flash(timing.flash_color, timing.flash_duration * rate) end when 3 self.flash(nil, timing.flash_duration * rate) end end end #-------------------------------------------------------------------------- # * Module: Cache addition # Adds a method for disposing bitmap resources #-------------------------------------------------------------------------- module Cache #-------------------------------------------------------------------------- # * Deletes a part of the stored hashed animation #-------------------------------------------------------------------------- def self.free(filename) @cache.delete("Graphics/Animations/"+filename) end end