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