Main Menu
  • Welcome to The RPG Maker Resource Kit.

Balloon Animations

Started by Arrow, August 09, 2009, 06:48:27 PM

0 Members and 1 Guest are viewing this topic.

Arrow

Okay, I copied Sprite_Character and pasted it under Materials. Yes, I am a noob. Here's what I've got (Pay attention to lines 122 and 144, that's all I changed.)

#==============================================================================
# ** Sprite_Character
#------------------------------------------------------------------------------
#  This sprite is used to display characters. It observes a instance of the
# Game_Character class and automatically changes sprite conditions.
#==============================================================================

class Sprite_Character < Sprite_Base
  #--------------------------------------------------------------------------
  # * Constants
  #--------------------------------------------------------------------------
  BALLOON_WAIT = 12                  # Final balloon frame wait time
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :character
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     viewport  : viewport
  #     character : character (Game_Character)
  #--------------------------------------------------------------------------
  def initialize(viewport, character = nil)
    super(viewport)
    @character = character
    @balloon_duration = 0
    update
  end
  #--------------------------------------------------------------------------
  # * Dispose
  #--------------------------------------------------------------------------
  def dispose
    dispose_balloon
    super
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    super
    update_bitmap
    self.visible = (not @character.transparent)
    update_src_rect
    self.x = @character.screen_x
    self.y = @character.screen_y
    self.z = @character.screen_z
    self.opacity = @character.opacity
    self.blend_type = @character.blend_type
    self.bush_depth = @character.bush_depth
    update_balloon
    if @character.animation_id != 0
      animation = $data_animations[@character.animation_id]
      start_animation(animation)
      @character.animation_id = 0
    end
    if @character.balloon_id != 0
      @balloon_id = @character.balloon_id
      start_balloon
      @character.balloon_id = 0
    end
  end
  #--------------------------------------------------------------------------
  # * Get tile set image that includes the designated tile
  #     tile_id : Tile ID
  #--------------------------------------------------------------------------
  def tileset_bitmap(tile_id)
    set_number = tile_id / 256
    return Cache.system("TileB") if set_number == 0
    return Cache.system("TileC") if set_number == 1
    return Cache.system("TileD") if set_number == 2
    return Cache.system("TileE") if set_number == 3
    return nil
  end
  #--------------------------------------------------------------------------
  # * Update Transfer Origin Bitmap
  #--------------------------------------------------------------------------
  def update_bitmap
    if @tile_id != @character.tile_id or
       @character_name != @character.character_name or
       @character_index != @character.character_index
      @tile_id = @character.tile_id
      @character_name = @character.character_name
      @character_index = @character.character_index
      if @tile_id > 0
        sx = (@tile_id / 128 % 2 * 8 + @tile_id % 8) * 32;
        sy = @tile_id % 256 / 8 % 16 * 32;
        self.bitmap = tileset_bitmap(@tile_id)
        self.src_rect.set(sx, sy, 32, 32)
        self.ox = 16
        self.oy = 32
      else
        self.bitmap = Cache.character(@character_name)
        sign = @character_name[/^[\!\$]./]
        if sign != nil and sign.include?('$')
          @cw = bitmap.width / 3
          @ch = bitmap.height / 4
        else
          @cw = bitmap.width / 12
          @ch = bitmap.height / 8
        end
        self.ox = @cw / 2
        self.oy = @ch
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Update Transfer Origin Rectangle
  #--------------------------------------------------------------------------
  def update_src_rect
    if @tile_id == 0
      index = @character.character_index
      pattern = @character.pattern < 3 ? @character.pattern : 1
      sx = (index % 4 * 3 + pattern) * @cw
      sy = (index / 4 * 4 + (@character.direction - 2) / 2) * @ch
      self.src_rect.set(sx, sy, @cw, @ch)
    end
  end
  #--------------------------------------------------------------------------
  # * Start Balloon Icon Display
  #--------------------------------------------------------------------------
  def start_balloon
    dispose_balloon
    @balloon_duration = 4 * 8 + BALLOON_WAIT
    @balloon_sprite = ::Sprite.new(viewport)
    @balloon_sprite.bitmap = Cache.system("Balloon")
    @balloon_sprite.ox = 16
    @balloon_sprite.oy = 32
    update_balloon
  end
  #--------------------------------------------------------------------------
  # * Update Balloon Icon
  #--------------------------------------------------------------------------
  def update_balloon
    if @balloon_duration > 0
      @balloon_duration -= 1
      if @balloon_duration == 0
        dispose_balloon
      else
        @balloon_sprite.x = x
        @balloon_sprite.y = y - height
        @balloon_sprite.z = z + 200
        if @balloon_duration < BALLOON_WAIT
          sx = 7 * 32
        else
          sx = (7 - (@balloon_duration - BALLOON_WAIT) / 4) * 32
        end
        sy = (@balloon_id - 1) * 32
        @balloon_sprite.src_rect.set(sx, sy, 32, 32)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Dispose of Balloon Icon
  #--------------------------------------------------------------------------
  def dispose_balloon
    if @balloon_sprite != nil
      @balloon_sprite.dispose
      @balloon_sprite = nil
    end
  end
end


How much of this can I trim away? How can I make the script smaller and more efficient?

The most important question I have, though, is how can I make the last four frames repeat a few times? I tried making a new variable and checking that, but it just makes it freeze on the last frame.

Ideally it would work like this:

1. Animation hits end frame
2. Animation loops back to fourth from last frame
3. Animation plays
R. Repeat steps 1-3 once more.
4. End animation.

How can I do this? I know it's probably quite simple.

modern algebra

Well, you can trim away most of it if you only changed two lines. Basically, you can delete from your script any method you did not alter. So if the only methods you changed were update_balloon and start_balloon, then every other method could be deleted from your script. You can trim away even more if you alias. So the start_balloon method is right now:


 def start_balloon
   dispose_balloon
   @balloon_duration = 4 * 8 + BALLOON_WAIT
   @balloon_sprite = ::Sprite.new(viewport)
   @balloon_sprite.bitmap = Cache.system("Balloon")
   @balloon_sprite.ox = 16
   @balloon_sprite.oy = 32
   update_balloon
 end


it could become:


alias anmus_blnanim_strtblln_8fh3 start_balloon
def start_balloon (*args)
 @balloon_duration = 4 * 8 + BALLOON_WAIT
 anmus_blnanim_strtblln_8fh3 (*args) # Run Original Method
end


As for making the balloon repeat, you have the right idea to introduce a counting variable; I don't know if you're current edits are appropriate though, unless you seek to reduce the time the balloon takes to complete.

If I were to approach it, I would initialize a counting variable in start_balloon, and have that advance each time you reach the end of the circuit until it reaches 3. I can write that for you if you need me to, but the basic idea is that the way this thing counts is this:


         sx = (7 - (@balloon_duration - BALLOON_WAIT) / 8) * 32


That line determines the x position of the rect it takes from the balloon animation sheet. If we remove the *32 at the end, then what we basically have is the determination of which frame of the animation we are on.

@balloon_duration tracks the number of frames (time) the animation is played, changing to the next animation frame every 8 time frames (by default). Sorry for using frame in two senses here; I will try to specify each time I use the word. BALLOON_WAIT is the constant that holds how many time frames the last animation frame is held onto before disposing. So, to put numbers to everything, BALLOON_WAIT is 12 by default, and @balloon_duration is 8 * 8 + BALLOON_WAIT when it is initialized, meaning that it is 64 + 12 = 76 time frames. @balloon_duration reduces by one every time frame.

SO:

The first time frame the balloon is played, @balloon_duration is reduced to 75. The frame we therefore get is:

7 - ((75 - 12) / 8) = 7 - (63 / 8) = 7 - 7 = 0

This will continue until @balloon_duration hits 67, at which point we get:

7 - (67 - 12) / 8) = 7 - (55 / 8) = 7 - 6 = 1

so we move to the next frame of the animation here.

The reason I am mentioning this is because we can follow from that the fourth to last frame is shown when @ballon_duration is equal to 43

7 - ((43 - 12) / 8) = 7 - 3 = 4

We can further reason that once @balloon_duration is equal to BALLOON_WAIT, then that is when the final frame has played out its first 8 frames. Thus, if at that moment we reset @balloon_duration to 43, then the animation will return to the 4th from last frame. We'd use the counting variable to count how many times we reset @balloon_duration, and then we just don't reset it once the counting variable gets up to 2.

Anyway, it's pretty simple to code, but I figure I'd see if you could decipher the confused jumble of words I just typed first.

Arrow

Okay, I've read over this repeatedly, and I feel like I'm getting the gist of what you're saying here. It makes sense...I just can't figure out what I'm supposed to do with it all.

It is partially a jumble of words, but I've got the basic concept- I just need a little help implementing it. If we could sit down in IRC and chat this out or something that would be grand.

modern algebra

Well, I'm pretty busy for the next couple days, so we wouldn't be able to chat until a couple days from now a - essentially what I'm saying is that you want to reset @balloon_duration when it reaches BALLOON_WAIT

if @balloon_duration == BALLOON_WAIT && @as_repeat_count < 2
  @balloon_duration += (8*4)
  @as_repeat_count += 1
end


I think that would work if you placed it before all of the rest of the code in update_balloon. You would need to initialize @as_repeat_count somewhere though - initialize would be the best place I think. Both changes can easily be aliased, by the way.

Arrow

In order for it to work quite properly, I had to change that 8*4 to a 4*4, so it didn't repeat the initial pop-up frames. You wouldn't know that as you haven't seen my animation, but just the same. Also, in order for it to extend the animation every time, I had to reset the @as_repeat_count to zero in the termination event- other wise they go back to normal after the first time the effect occurs.

THANK YOU. :D