Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Play animation anywhere, anytime

Play Database Animation 1.2

What does this script do?
RMXP has a great system to create animations in the database, but it forces you to use them on a sprite /event.
This script lets you play those animations anywhere you want: in the Title screen, in the menu, in custom scenes, or just on the map on a certain spot.
It can play several animations at once, and should be compatible with anything.

Instructions:
use
Animation.new(id, x, y)

* Optional values: z, freeze. Read the instructions in the code.

code
[rgss]#---------------------------------------------------------------------
# ** Animation
#---------------------------------------------------------------------
#
#  V.1.2
#  Made by: silverwind & ForeverZer0
#    
#  * This class enables playing a database animation
#    in every scene, including costum ones.
#
#  * Instructions:
#    put the following code in a script / an event's script call:
#    Animation.new(id,x,y)
#    where  id= the number of the animation in the database
#           x= screen x
#           y= screen y
# * Notes:
#   - If the animation shows below something else on the screen, use:
#     Animation.new(id,x,y,z)
#      Experiment with z's value. The default value is 9000,
#      so try higher numbers.
#   - freeze
#     Animation.new(id,x,y,z,true)
#     ^ use this code to freeze the game until the animation is done.
#     useful when you want to play an animation during a scene change.
#     (ie, going from the menu screen to the map screen)
#---------------------------------------------------------------------
 
 
class Animation < RPG::Sprite
 
  attr_accessor :frames           # frame count (from frame_max down to 0)
 
  def initialize(id, x, y, z = 9000, freeze=false)
    viewport = Viewport.new(0, 0, 640, 480)
    viewport.z = z
    super(viewport)
    self.x, self.y = x, y
    @frames = $data_animations[id].frame_max
    hit = true
    self.animation($data_animations[id], hit)
    Graphics.play_animation(self, freeze)
  end
 
  def dispose
    self.viewport.dispose
    super
  end
 
end
 
module Graphics
 
  class << self
   
    def freeze_play_animation(frames)
      if @animations != nil && @animations.size > 0
        for i in 0..frames : update end
      end
    end
   
    def clear_animations_on_scene_change
      return if @last_scene.nil?
      if @last_scene != $scene.class.name
        @animations.each_index {|i|
              @animations.dispose
              }
        @animations = []
      end
    end
   
    def play_animation(animation, freeze)
      @animations = [] if @animations == nil
      @animations.push(animation)
      if freeze
        freeze_play_animation(animation.frames)
      end
    end
   
    alias animation_update update
    def update
      if @animations != nil && @animations.size > 0
        @animations.compact!
        @animations.each_index {|i|
          @animations.update
          @animations.frames -= 1
          if @animations.frames < 0
            @animations = @animations.dispose
          end
        }
      end
      animation_update
      clear_animations_on_scene_change
      @last_scene = $scene.class.name
    end
  end
 
 
end
[/rgss]

older versions
[rgss]#---------------------------------------------------------------------
# ** Animation
#---------------------------------------------------------------------
#
#  V.1.1
#  Made by: silverwind & ForeverZer0
#    
#  * This class enables playing a database animation
#    in every scene, including costum ones.
#
#  * Instructions:
#    put the following code in a script / an event's script call:
#    Animation.new(id,x,y)
#    where  id= the number of the animation in the database
#           x= screen x
#           y= screen y
# * Notes:
#   - If the animation shows below something else on the screen, use:
#     Animation.new(id,x,y,z)
#     Experiment with z's value. The default value is 9000,
#     so try higher numbers.
#   - 'hit' is a true/false value, related to the database animation
#      I'm not sure what it does, but in case you need to change it, use:
#      Animation.new(id,x,y,z,hit)
#---------------------------------------------------------------------
 
 
class Animation < RPG::Sprite
 
  attr_accessor :frames                      # frame count (from frame_max down to 0)
 
  def initialize(id, x, y, z = 9000, hit = true)
    viewport = Viewport.new(0, 0, 640, 480)
    viewport.z = z
    super(viewport)
    self.x, self.y = x, y
    @frames = $data_animations[id].frame_max
    self.animation($data_animations[id], hit)
    Graphics.play_animation(self)
  end
 
  def dispose
    self.viewport.dispose
    super
  end
 
end
 
module Graphics
 
  class << self
   
    def play_animation(animation)
      @animations = [] if @animations == nil
      @animations.push(animation)
    end
   
    alias animation_update update
    def update
      if @animations != nil && @animations.size > 0
        @animations.compact!
        @animations.each_index {|i|
          @animations.update
          @animations.frames -= 1
          if @animations.frames < 0
            @animations = @animations.dispose
          end
        }
      end
      animation_update
    end
  end
end
[/rgss]

[rgss] 
#==============================================================================
# ** Animation
#------------------------------------------------------------------------------
#  This class shows a database animation on the screen.
#   should work outside scene_map /battle.
#
#  Instructions:
#    put the following code in a script / an event's script call:
#    Animation.new(id,x,y)
#    where  id= the number of the animation in the database
#           x= screen x
#           y= screen y
#  Notes:
#   if the animation shows below something else on the screen, use:
#   Animation.new(id,x,y,z)
#   experiment with z's value. it's 9000 by default, so try higher numbers.
#  
#==============================================================================
class Animation
 
  def initialize(anim_id, x, y, z=9000, hit=true)
    view = Viewport.new(0, 0, 640, 480)
    view.z = z
    @sprite =  RPG::Sprite.new(view)
    @sprite.x = x
    @sprite.y = y
    @sprite.z = z
    @anim_file = $data_animations[anim_id]
    run_it(x, y, hit)
    @sprite.viewport.dispose
    dispose
  end
 
  def dispose()
    @sprite.dispose()
  end
 
  def run_it(x, y, hit)
    @sprite.animation(@anim_file, hit)
    size = @anim_file.frame_max
    for i in 0...size
      @sprite.update()
      Graphics.update()
      $game_screen.update
    end
  end
 
end
[/rgss]
 
I'm curious why you would purposefully have the rest of the game freeze during the animation's playback. Personally I think it would be better to have the game proceed normally during the animation, or at the very least allow the player to choose.
 
I did this script cause I needed to play an animation during Scene_Title. so I've searched scripts which let you play an animation out of map/battle, but those usually come as a part of a CMS. there was one using threads +some fancy weather system (by MCgamer), which was an overkill, imo (it also freezes the game, btw).

not freezing would be better, but it complicates things immensely.
if, for example, I update the animation in each scene's update method, or in Graphics.update, the animation will play in slow-motion or freeze completely in some scenes. I'll have to add my code into every scene- several times in longer update methods, making it incompatible with custom scenes.
another option is to re-invent the wheel, and write the RPG::Sprite.animation script from scratch, and make it replicate the animation in the database accurately (did I mention overkill?)

in short, ease of use + 100% compatibility > avoiding freeze for 1-2 seconds.

do you have a simple way to avoid freezing? I'd love to hear it.
 
I wish it was this easy.
a quick testing made me drown in errors.
like I mentioned, some scenes (like scene_map /scene_battle) have huge update methods that freeze the animation. if the animation is done by a script call, RMXP quits (cause it takes too long). it also creates bugs if you're in scene_title or in the middle of changing scenes.

Listen, the script may not be perfect, but it WORKS. it does play the animation, and the freeze is hardly noticeable, except in scene map/ costum battle systems (where you can use RMXP's 'show battle animation' command). if the freezing bugs you, there are other scripts out there.
 
Hmmm. You are correct in the regard that in it takes more than simple $scene.update. Another solution is to alias the Graphics module's update method. Then it could be compatible with absolutely everything, even if there is no scene. Something like this:

[rgss]class Animation < RPG::Sprite
 
  attr_accessor :frames
 
  def initialize(id, x, y, z = 9000, hit = true)
    viewport = Viewport.new(0, 0, 640, 480)
    viewport.z = z
    super(viewport)
    self.x, self.y = x, y
    @frames = $data_animations[id].frame_max
    self.animation($data_animations[id], hit)
    Graphics.play_animation(self)
  end
 
  def dispose
    self.viewport.dispose
    super
  end
 
end
 
module Graphics
 
  class << self
   
    def play_animation(animation)
      @animations = [] if @animations == nil
      @animations.push(animation)
    end
   
    alias animation_update update
    def update
      if @animations != nil && @animations.size > 0
        @animations.compact!
        @animations.each_index {|i|
          @animations.update
          @animations.frames -= 1
          if @animations.frames < 0
            @animations = @animations.dispose
          end
        }
      end
      animation_update
    end
  end
end
[/rgss]

I didn't mean any insult, but in my opinion the freeze WAS noticeable, and it would be even worse for longer animations. 10 frames might not be noticed too bad, but if someone has a 3 or 4 second animation, its going to be hard to ignore.
 
thank you ^^ that's an elegant solution.. I was going to try using threads, but this works too.
I'll add you to the script credits. (do you want to forbid commercial use? if so tell me, and I'll add that to the header)
I'm sure this script will be useful to many, especially people working on a custom animated scene.

Edit:
tiny problem with scene-changes: if done close to a scene change, the animation will not appear in the right scene, but in the new one. ie: if you have an animation play on the menu when canceling, the animation will play on the map screen, not on the menu screen.
so I'll take your advice & let the user choose whether to freeze until it ends or not.
I'll also clear animations when a scene changes.
[rgss]#---------------------------------------------------------------------
# ** Animation
#---------------------------------------------------------------------
#
#  V.1.2
#  Made by: silverwind & ForeverZer0
#    
#  * This class enables playing a database animation
#    in every scene, including costum ones.
#
#  * Instructions:
#    put the following code in a script / an event's script call:
#    Animation.new(id,x,y)
#    where  id= the number of the animation in the database
#           x= screen x
#           y= screen y
# * Notes:
#   - If the animation shows below something else on the screen, use:
#     Animation.new(id,x,y,z)
#      Experiment with z's value. The default value is 9000,
#      so try higher numbers.
#   - freeze
#     Animation.new(id,x,y,z,true)
#     ^ use this code to freeze the game until the animation is done.
#     useful when you want to play an animation during a scene change.
#     (ie, going from the menu screen to the map screen)
#---------------------------------------------------------------------
 
 
class Animation < RPG::Sprite
 
  attr_accessor :frames           # total frames in the animation
 
  def initialize(id, x, y, z = 9000, freeze=false)
    viewport = Viewport.new(0, 0, 640, 480)
    viewport.z = z
    super(viewport)
    self.x, self.y = x, y
    @frames = $data_animations[id].frame_max
    hit = true
    self.animation($data_animations[id], hit)
    Graphics.play_animation(self, freeze)
  end
 
  def dispose
    self.viewport.dispose
    super
  end
 
end
 
module Graphics
 
  class << self
   
    def freeze_play_animation(frames)
      if @animations != nil && @animations.size > 0
        for i in 0..frames : update end
      end
    end
   
    def clear_animations_on_scene_change
      return if @last_scene.nil?
      if @last_scene != $scene.class.name
        @animations.each_index {|i|
              @animations.dispose
              }
        @animations = []
      end
    end
   
    def play_animation(animation, freeze)
      @animations = [] if @animations == nil
      @animations.push(animation)
      if freeze
        freeze_play_animation(animation.frames)
      end
    end
   
    alias animation_update update
    def update
      if @animations != nil && @animations.size > 0
        @animations.compact!
        @animations.each_index {|i|
          @animations.update
          @animations.frames -= 1
          if @animations.frames < 0
            @animations = @animations.dispose
          end
        }
      end
      animation_update
      clear_animations_on_scene_change
      @last_scene = $scene.class.name
    end
  end
 
 
end
[/rgss]
 
You don't need to credit me, nor do I care about commercial use, but I appreciate the thought.

The scene problem could be solved something like this:

  • In the Animation class, add an attr_reader called "scene" or whatever
  • In Animation's initialize, add a @scene = $scene.class
  • In the Graphic's update where each animation is updated, add an additional check:
    Code:
    if $scene.is_a?(animation.scene)
  • If false, dispose the animation and remove it from the array
 
well, your name is in the credits, if you want it or not ;)
I already fixed the scene problem, and updated the first post with the new code. should have been more clear about it in my last post ^^;
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top