Jump to content
Tuckie

animation of draw_text() ?

Recommended Posts

Hello, all.

 

I'm working on a script (VX Ace) where I can draw text, and have that text animate. So far I've got a few key features working:

  • script-callable class that draws characters one at a time (sort of) with proper spacing
  • can detect 'escape keys' and draw different kinds of text based on desired 'animation'

However, there are a few things I don't quite understand, or know how to implement as well:

  • While I have created a loop that draws each character one at a time, it seems to iterate through that loop so fast, all of the desired text displays at the same time (on the same frame). How would I go about controlling the time it takes for it to draw out a new character?
  • I currently have two 'animations' in the script: a 'shake effect' where the text is drawn with a random number between 2 and -2 two it's coordinates, and a 'wave', where the sprite's Y coordinate is affected by a sine wave. In the script, these are drawn via a draw_text(), which draws them correctly, but only draws them once. My hope is to find a way to re-draw them each frame so that the characters would continue to have motion. My thoughts were to send the standard draw_text arguments to a new class for each of the animated characters, which would handle it's animation, but am still not sure how that would work.
  • Finally, the text displayed itself doesn't seem to stay for more than a few frames. I have been testing the script so far by giving an event a script call to make the text, and when you interact with it, the text will appear but go away after about a second or so, and I'm not sure why.

 

Here is the full code I have been working on so far. I still consider myself really new to coding, so sorry if it's messy.

 

 

module TalkieBoxSettings
  
  #------------------------#
  # General Settings       #
  #------------------------#
  
  FLOATUP = true #sets whether a textbox has a starting animation of floating up
  
  #------------------------#
  # Position Settings      #
  #------------------------# 
  TALKIEBOX_X = 0
  TALKIEBOX_Y = 280
  # Position of text box, where 0,0 is top left. Use ur algebra bro
  
  TALKIEBOX_HEIGHT = 80
  TALKIEBOX_WIDTH  = 300
  # Size(in pixels) of the text box
  
  FACE_T_X = 0
  FACE_T_Y = 0
  # position (in pixels) of portrait/bust RELATIVE to X and Y of text box
  
  #------------------------#
  # Spacing Settings       #
  #------------------------#
  
  NCHARWIDTH = 10  #spacing between each character
  LCHARWIDTH = 2   #spacing to add to characters 'W' and 'M' 
  SCHARWIDTH = 4   #spacing between shorter characters such as: i or !
  
  LINE_END    = 40 #amount of desired characters per line of text
  # space - dont worry about it
  # i - dont worry about it
  TEXT_SPEED = 3   #Amount of frames before each character is drawn
  
  
end #module TalkieBoxSettings

class TalkieBox < Window_Base
  
 def initialize(message)
   super(-6, -12, 648, 480)
   self.z = 110
   self.back_opacity = 0
   
  @space      = 0 #
  @cutoff     = 0 #
  @i          = 0 # 'i' for looping purposes
  @lineheight = 0 #
  @animation  = 0 
  @t          = 0
  @extra      = 0
  @message    = message
  drawtext(message)
 end #initialize
 
 
 def drawtext(message)
   
  text = message.each_char.to_a
  textlength = text.length
   while @i <= textlength + 2000 do
     @t += 1
     @length = 0
     puts(text[@cutoff])
     
     if text[@cutoff] == "~"
       @cutoff += 1
       @animation = text[@cutoff].to_i
       @cutoff += 1
     end #if text[@cutoff] == "~"
     if text[@cutoff] == "m" or "w"
       @extra += TalkieBoxSettings::LCHARWIDTH
     end #if text[@cutoff] == "~"   
        while text[@cutoff] != " " and @i <= message.length do    
          @i += 1
          @length += 1        
        end #while text[cutoff]
      
        if @space + @length > TalkieBoxSettings::LINE_END #check if end of line, and make new line
          @lineheight += 14
          @space = 0
          @extra = 0
        end # space + length > TalkieBoxSettings::LINE_END
        
        
        case @animation
        when 0
           contents.draw_text(@space * TalkieBoxSettings::NCHARWIDTH + @extra,@lineheight,100,100,text[@cutoff],0)
        
        when 1
           contents.draw_text(@space * TalkieBoxSettings::NCHARWIDTH + rand(3) + @extra,@lineheight +rand(3),100,100,text[@cutoff],0)
        when 2
           so    = @t + @i
           shift = Math.sin( 3 * so * 5) * 2
           contents.draw_text(@space * TalkieBoxSettings::NCHARWIDTH + @extra,@lineheight + shift,100,100,text[@cutoff],0)
        end # case animation
      
      @i = @i + 1
      @space += 1
      @cutoff += 1
   end #while i <=...  
   
 end #drawtext
 
 
 def update

 end

 def drawportrait(imagename)
  #code for portraits
  #Cache.faces("imagename")
 end #drawportrait
 
end #class TalkieBox

class ShakeText < Window_Base

    def initialize ( x, y, w, h, text, allign = 0)
      # create content window
      super(-6, -12, 648, 480)
      self.z = 110
      self.back_opacity = 0  
        
        # create variables for text location
        @x = x
        @y = y
        @w = w
        @h = h
        @text = text
        @allign = 0
        
        update
    end # def initialize

    def update
        contents.clear
        draw_text( @x + rand(2) - rand(2), @y + rand(2) - rand(2), @w, @h, @text, @allign)  
    end #update

end # Class ShakeText < Window_Base

 

 

 

If anything, what I would like help with most is if anyone can describe how animation is possible in RGSS3, for instance, making use of update method? Thanks in advance.

Share this post


Link to post
Share on other sites

Try using Draw_Text_Ex for one at a time stuff... it already can draw text one at a time in Window_Message. Just looping though the text won't do, you have to set up something like Fiber.yeild calls like Window_Message does to do other things, or at least call Graphics.update. My advice for animated text is to make a sprite for the text that is displayed over the static text in the background instead, otherwise you basically have to redraw the whole thing every frame which is going to be slow as heck and not work very well.

Share this post


Link to post
Share on other sites

Try using Draw_Text_Ex for one at a time stuff... it already can draw text one at a time in Window_Message. Just looping though the text won't do, you have to set up something like Fiber.yeild calls like Window_Message does to do other things, or at least call Graphics.update. My advice for animated text is to make a sprite for the text that is displayed over the static text in the background instead, otherwise you basically have to redraw the whole thing every frame which is going to be slow as heck and not work very well.

Thanks for the response. Actually, between the time I posted this and saw your response I had figured out a way to implement what I had written into the default Window_Base, so I'm going to try to work this into the default message boxes. I'm looking into using sprites to create letters that move, but am not sure of a few things, still. Where I am having trouble with is thinking of a sane way to control each Sprite. This is probably due to inexperience, but all I can think of is for each character while the @animation variable is not 0 (ie a distinct animation), to create a new instance of a class which handles it's own animation. The problem with that is I'm not sure how each object could have a different name, and from there be deleted when the message box is done? Or am I able to create a class derivative of Sprite, and create a custom update method that handles it's animation? It doesn't seem as if I'm thinking this through correctly. Also, doing something like @sprite.bitmap.drawtext(arguments) just gives me a nomethod error, so I'm not sure how to even do that?

Again, thanks for the insight.

 

Also, for what it's worth here's what I now have written.

 

 

#==============================================================================
# ** Window_Base
#------------------------------------------------------------------------------
#  This is a super class of all windows within the game.
#==============================================================================

class Window_Base < Window
  
  alias Tuckie_Wiggly_Ani   initialize
  def initialize(x, y, width, height)
    @animation = 0
    @t         = 0
    Tuckie_Wiggly_Ani(x, y, width, height)
  end
  #--------------------------------------------------------------------------
  # * Character Processing
  #     c    : Characters
  #     text : A character string buffer in drawing processing (destructive)
  #     pos  : Draw position {:x, :y, :new_x, :height}
  #--------------------------------------------------------------------------
  def process_character(c, text, pos)
    print(@animation)
    case c
    when "\n"   # New line
      process_new_line(text, pos)
    when "\f"   # New page
      process_new_page(text, pos)
    when "\e"   # Control character
      process_escape_character(obtain_escape_code(text), text, pos)
    else        # Normal character
      case @animation
      when 0
      process_normal_character(c, pos)
      when 1
      process_shake_character(c, pos)
      when 3
      process_wave_character(c, pos)
      else
      process_normal_character(c, pos)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Normal Character Processing
  #--------------------------------------------------------------------------
  def process_normal_character(c, pos)
    text_width = text_size(c).width
    draw_text(pos[:x], pos[:y], text_width * 2, pos[:height], c)
    pos[:x] += text_width
  end
  
  
  #--------------------------------------------------------------------------
  # * Shake Character Processing
  #--------------------------------------------------------------------------
  def process_shake_character(c, pos)
    Graphics.update
    text_width = text_size(c).width
    draw_text(pos[:x] + rand(3) - rand(3), pos[:y] + rand(3) - rand(3), text_width * 2, pos[:height], c)
    pos[:x] += text_width
  end
  
  #--------------------------------------------------------------------------
  # * Wave Character Processing
  #--------------------------------------------------------------------------
  def process_wave_character(c, pos)
    Graphics.update
    @t += 1
    so    = @t + @t
    shift = Math.sin( 3 * so * 5) * 3
    text_width = text_size(c).width
    draw_text(pos[:x], pos[:y] + shift, text_width * 2, pos[:height], c)
    pos[:x] += text_width
  end

  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  alias wiggleupdate update
  def update
    wiggleupdate
    
  end
  
  
  #--------------------------------------------------------------------------
  # * Control Character Processing
  #     code : the core of the control character
  #            e.g. "C" in the case of the control character \C[1].
  #--------------------------------------------------------------------------
  def process_escape_character(code, text, pos)
    case code.upcase
    when 'C'
      change_color(text_color(obtain_escape_param(text)))
    when 'I'
      process_draw_icon(obtain_escape_param(text), pos)
    when '{'
      make_font_bigger
    when '}'
      make_font_smaller
    when 'T'
      @animation = 0
    when 'Y'
      @animation = 3
    when 'U'
      @animation = 1
    end
  end
end

Also, for some reason the only escape keys I can get to work are T and Y. For instance I have one in there for U, but if you try to use it it just skips over displaying characters until a punctuation mark appears? I can't really figure out why that's happening either. EDIT: it seems to have something to do with another script, as it works as intended in a blank project.

 

 

Edited by Tuckie

Share this post


Link to post
Share on other sites

Subclassing the Sprite class to make a custom update method is probably the best way to control the sprite, yes. You should look at Window_Message for more infor about how the message box works. I wish I could help you more, and I am not sure if my advice was too helpful, but this is bound to be a big project with a lot of really annoying details to work out.

 

Good luck whatever you do! *sprinkles fairy dust on you*

Share this post


Link to post
Share on other sites

tf8RLaA.gif

 

Hello, again...

I became very busy and hadn't gotten a chance to continue working on this for a while, but now I am very close to being done. I got really halted for a while on being able to manage and store each character. I didn't realize you could just make an array of objects until recently, which made the rest really easy.

As the GIF shows, I have pretty much everything working, except for one small bug. The text doesn't begin to animate until all the text in the box has been drawn.

This seems to be some sort of issue with Window_Message's fiber system.

I added a method to the sprite class that changes it's position based on a sine wave, and i call that method on every letter on Window_Message's update method, which is how it changes every frame. But it doesn't call the update method at all until all text has appeared in the box.

I can post all the code if needed, but if someone knows shorthand how i could call my method during that process, it would help me a lot. Thanks one more time.

Share this post


Link to post
Share on other sites

Hmm, I tried that, process_character, even fiber_main, to no luck. Interestingly, on wait_for_one_character, while it doesn't update until they are all on-screen, the animation plays faster for the first few frames.

Even Game_Interpreter's update doesn't fire off when it's drawing characters?

 

UPDATE: Alright, after messing around a bit, I seemed to have found a partial fix. In the method that creates each waving character I call Graphics.update() so that the characters 'scroll' onto the screen like the normal characters. When I get rid of that, The characters animate while text scrolls, but each waving character comes out on the same frame. I can't find anywhere to put a Graphics.update that works.

 

I tried adding a Graphics.update to the wave() method that I added to Sprite, so it updates once every time the letter is called to move. This achieves the scrolling effect, but the whole text scrolling slows down even more which is not desireable.

TMLEA1s.gif

Edited by Tuckie

Share this post


Link to post
Share on other sites

How are you creating the sprites? It looks like you are creating all the sprites at once, rather then pushing each letter on to the array as it's drawn like I thought you were. Maybe I can look and see if I can find a better way to do it if I saw the code.

 

Edit: Actually try calling wait_for_one_character instead of Graphics.update in the method that creates the sprites.

Edited by KilloZapit

Share this post


Link to post
Share on other sites

 

 

class Sprite
  
  alias Tuckie_Wiggly_Sprite   initialize
  def initialize(*args)
    @wave = 0
    Tuckie_Wiggly_Sprite(*args)
  end
  
  def setwave(x)
    @wave = x

  end  
  
  def wave
    @wave += 0.6
    surf = Math.sin(@wave / 4) * 4
    self.y = self.oy + surf.round
  end
  
  def shake

  end
end

#==============================================================================
# ** Window_Base
#------------------------------------------------------------------------------
#  This is a super class of all windows within the game.
#==============================================================================

class Window_Base < Window
  
  alias Tuckie_Wiggly_Ani   initialize
  def initialize(x, y, width, height)
    @wind_y    = y
    @animation = 0
    @t         = 0
    @test      = 0
    @wave      = 0
    @wavecount = 0
    $wavechars = []
    @shakecount= 0
    @shakechars= []
    $waving    = false
    Tuckie_Wiggly_Ani(x, y, width, height)
  end
  #--------------------------------------------------------------------------
  # * Wiggle Processing
  #-------------------------------------------------------------------------- 
  def wiggle()
    if $waving && $wavechars != nil && @wavecount > 0
      $wavechars.each do |letter|
        letter.wave
      end 
    end
  end 
  #--------------------------------------------------------------------------
  # * Character Processing
  #     c    : Characters
  #     text : A character string buffer in drawing processing (destructive)
  #     pos  : Draw position {:x, :y, :new_x, :height}
  #--------------------------------------------------------------------------
  def process_character(c, text, pos)

    case c
    when "\n"   # New line
      process_new_line(text, pos)
    when "\f"   # New page
      process_new_page(text, pos)
    when "\e"   # Control character
      process_escape_character(obtain_escape_code(text), text, pos)
    else        # Normal character
      case @animation
      when 0
      process_normal_character(c, pos)
      when 1
      process_shake_character(c, pos)
      when 3
      process_wave_character(c, pos)
      else
      process_normal_character(c, pos)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Normal Character Processing
  #--------------------------------------------------------------------------
  def process_normal_character(c, pos)
    text_width = text_size(c).width
    draw_text(pos[:x], pos[:y] - 6, text_width * 2, pos[:height], c)
    pos[:x] += text_width
  end
  
  
  #--------------------------------------------------------------------------
  # * Shake Character Processing
  #--------------------------------------------------------------------------
  def process_shake_character(c, pos)

    if !$waving
      $waving = true
    end
    text_width = text_size(c).width
    rect = Rect.new(pos[:x], pos[:y], text_width, 30)
    @shakechars[@shakecount] = Sprite.new
    @shakechars[@shakecount].x =  pos[:x] + self.standard_padding
    bitmap = Bitmap.new(Graphics.width, Graphics.height)    
    @shakechars[@shakecount].bitmap = bitmap
    @shakechars[@shakecount].z = 500
    bitmap.draw_text(0, $messageheight + pos[:y] + self.standard_padding, text_width, 16, c, 0)
    
    @shakecount += 1
    
    pos[:x] += text_width
  end
  
  #--------------------------------------------------------------------------
  # * Wave Character Processing
  #--------------------------------------------------------------------------
  def process_wave_character(c, pos)
    if !$waving
      $waving = true
    end
    text_width = text_size(c).width#
    rect = Rect.new(pos[:x], pos[:y], text_width, 30)
    $wavechars[@wavecount] = Sprite.new
    $wavechars[@wavecount].x =  pos[:x] + self.standard_padding
    bitmap = Bitmap.new(Graphics.width, Graphics.height)    
    $wavechars[@wavecount].bitmap = bitmap
    $wavechars[@wavecount].z = 500
    bitmap.draw_text(0, $messageheight + pos[:y] + self.standard_padding, text_width, 16, c, 0)
    $wavechars[@wavecount].setwave(@wavecount)#^238
    pos[:x] += text_width #
    @wavecount += 1
  end

  
  
  #--------------------------------------------------------------------------
  # * Control Character Processing
  #     code : the core of the control character
  #            e.g. "C" in the case of the control character \C[1].
  #--------------------------------------------------------------------------
  def process_escape_character(code, text, pos)
    case code.upcase
    when 'C'
      change_color(text_color(obtain_escape_param(text)))
    when 'I'
      process_draw_icon(obtain_escape_param(text), pos)
    when '{'
      make_font_bigger
    when '}'
      make_font_smaller
    when 'T'
      @animation = 0
    when 'Y'
      @animation = 3
    when 'U'
      @animation = 1
    end
  end
end

class Window_Message < Window_Base
  
  alias Tuckie_Wiggly_Init initialize
  def initialize(*args)
    Tuckie_Wiggly_Init(*args) 
  end
  #--------------------------------------------------------------------------
  # * Update Window Position
  #--------------------------------------------------------------------------
  alias Tuckie_Wiggly_Get_Y update_placement
  def update_placement(*args)
    Tuckie_Wiggly_Get_Y(*args)
    $messageheight = self.y
  end  
  #--------------------------------------------------------------------------
  # * New Page
  #--------------------------------------------------------------------------
  alias Tuckie_Wiggly_New_Page new_page
  def new_page(text, pos)
    dispose_wiggle()
    Graphics.update
    Tuckie_Wiggly_New_Page(text, pos)
  end
  #--------------------------------------------------------------------------
  # * Close Window and Wait for It to Fully Close
  #--------------------------------------------------------------------------
  alias Tuckie_Wiggly_close_wait close_and_wait
  def close_and_wait
    dispose_wiggle()
    Tuckie_Wiggly_close_wait()
  end
  #--------------------------------------------------------------------------
  # * Free animated text
  #--------------------------------------------------------------------------
  def dispose_wiggle
    @wavecount  = 0
    @shakecount = 0
    $waving = false
    $wavechars.each do |letter|
      letter.dispose
    end
    @shakechars.each do |letter|
      letter.dispose
    end
  end
  #--------------------------------------------------------------------------
  # * Window Update
  #--------------------------------------------------------------------------  
   alias Tuckie_Wiggly_Update_Base update
   def update
     wiggle()
     Tuckie_Wiggly_Update_Base()
   end
end

 

 

Here is what I have. It's really messy as I've been doing a lot of changing recently.

wait_for_one_character there is something I actually tried. While that does draw it frame by frame, it doesn't seem to animate it correctly (potentially calling 2 changes in position per frame?). It also seems to interfere with how I dispose the characters, because when I open up a second text box, it shows an error (the Sprite object doesn't have an associated oy).

 

I know for sure that it IS drawing one character at a time. I overwrote process_character to go to a different letter drawing method depending on what a variabe, @animation is. @animation is controlled within the escape code method.

 

I was putting Graphics.update at the beginning of process_wave_character()

Edited by Tuckie

Share this post


Link to post
Share on other sites

But wait_for_one_character is something you really need. How does it mess up the animation?

 

Hmmm... you tend to use globals a lot and putting a lot of that code in Window_Base is probobly a bad idea... message windows aren't the only thing that uses that code after all. That's besides the point though.

 

Maybe I should play with it. :3

Share this post


Link to post
Share on other sites

Here's an example of what happens when I have wait_for_one_character at the beginning of process_wave_character(). I'll also not that wait_for_one_character already does happen, I'm pretty sure. Because process_normal_character() which is in the default script never had it, its probably being called beforehand.

 

 

2GKGZTi.gif

wwxtchS.png

 

 

In addition to the animation not looking the same, there seems to be interference when I open up a second box.

 

Feel free to play around if you want. I didn't need to use global variables for the array of wave characters, but I changed them to that when I was trying to include the update in other classes.

Share this post


Link to post
Share on other sites

Your problem is you never set the array of sprites to empty after you dispose them all.

 

Hehe try this version I made, though it uses different commands (/ANI[x] /OFF /WAV /SHK):

#==============================================================================
# ** Sprite_TextAnim
#------------------------------------------------------------------------------
#  Sprite subclass for text animations.
#==============================================================================


class Sprite_TextAnim < Sprite
 
  attr_accessor :anim_offset
  attr_accessor :anim_type
 
  def update
    return unless @anim_offset
    case @anim_type
      when 1
        @anim_offset += 0.115
        self.oy = Math.sin(@anim_offset) * 3
      when 2
        @anim_offset += 0.2
        self.ox = Math.sin(@anim_offset) * 3
        self.oy = Math.cos(@anim_offset) * -3
      when 3
        @anim_offset += 0.2
        self.zoom_x = 1 + Math.sin(@anim_offset) * 0.2
        self.zoom_y = 1 + Math.cos(@anim_offset) * 0.2
      else
        return
    end
  end
 
end

#==============================================================================
# ** Window_Message
#------------------------------------------------------------------------------
#  This message window is used to display text.
#==============================================================================

class Window_Message < Window_Base
 
  alias tuckie_wiggly_clear_instance_variables clear_instance_variables
  def clear_instance_variables
    tuckie_wiggly_clear_instance_variables
    @animchars = []
  end

  #--------------------------------------------------------------------------
  # * Normal Character Processing
  #--------------------------------------------------------------------------
  def process_normal_character(c, pos)
    if @anim_type && @anim_type > 0
      process_anim_character(c, pos)
    else
      super
    end
    wait_for_one_character
  end
 
  #--------------------------------------------------------------------------
  # * Animated Character Processing
  #--------------------------------------------------------------------------
  def process_anim_character(c, pos)
    text_width = text_size(c).width
    letter = Sprite_TextAnim.new(self.viewport)
    bitmap = Bitmap.new(text_width * 2, pos[:height])
    bitmap.font = self.contents.font
    bitmap.draw_text(0, 0, text_width * 2, pos[:height], c)
    letter.bitmap = bitmap
    letter.x = pos[:x] + self.standard_padding
    letter.y = self.y + standard_padding + pos[:y]
    letter.z = self.z + 10
    letter.anim_offset = @animchars.size
    letter.anim_type = @anim_type
    @animchars.push(letter)
    pos[:x] += text_width
  end
 
  #--------------------------------------------------------------------------
  # * Control Character Processing
  #     code : the core of the control character
  #            e.g. "C" in the case of the control character \C[1].
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_process_escape_character process_escape_character
  def process_escape_character(code, text, pos)
    case code.upcase
    when 'ANI' # Text Animation (by number)
      @anim_type = obtain_escape_param(text)
    when 'OFF' # No Text Animation
      @anim_type = 0
    when 'WAV' # Wave animation
      @anim_type = 1
    when 'SHK' # Shakey animation
      @anim_type = 2
    end
    tuckie_wiggly_process_escape_character(code, text, pos)
  end

  #--------------------------------------------------------------------------
  # * Close Window and Wait for It to Fully Close
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_close_wait close_and_wait
  def close_and_wait
    dispose_text_animation()
    tuckie_wiggly_close_wait()
  end
 
  #--------------------------------------------------------------------------
  # * Free animated text
  #--------------------------------------------------------------------------
  def dispose_text_animation
    @animchars.each do |letter|
      letter.dispose
    end
    @animchars = []
  end
 
  #--------------------------------------------------------------------------
  # * Window Update
  #--------------------------------------------------------------------------  
  alias tuckie_wiggly_update_base update
  def update
    update_text_animation()
    tuckie_wiggly_update_base()
  end
   
  #--------------------------------------------------------------------------
  # * Text Animation Processing
  #--------------------------------------------------------------------------
  def update_text_animation()
    unless @animchars.empty?
      @animchars.each do |letter|
        letter.update
      end
    end
  end
 
end

Other changes include:

 

Redoing the sprites so they are much smaller

Subclassing to move the sprite code to a new class

Changing the animation type to be a aspect of the sprite not the window

Made sure to set the sprite bitmap's font to the same as the windows font

Merging code in Window_Base into Window_Message (because Window_Base can't make use of it anyway and it's simpler this way)

Made it compatible with my wordwrap script (I think) by changing it to overwrite process_normal_character instead of process_character.

Changed globals to instance variables

Changed the wave's look slightly and two new silly animations

Changed the methods that started with uppercase to lowercase (honestly I am not sure how they even worked, because it gave errors for me because only constants are supposed to start with upper case letters)

Cleaned up code

Edited by KilloZapit

Share this post


Link to post
Share on other sites

OH! So the self.oy error was that when I disposed each letter, it was still an array of disposed Sprites? That makes a lot of sense now.

When I first started to figure out the stuff with arrays of objects, a friend of mine told me to use stacks, I just didn't know enough at the time.

Also, that is weird. I wasn't getting any errors for the capitalized aliased methods. I should probably go back to my other scripts and change that.

 

Wow, that's very different! And a lot simpler to add additional animations. That would have been my next step, a more streamlined way of drawing the characters that didn't involve tons of copy and pasting. Just looking at all the differences, I can tell I have a ways to go with Ruby. You've changed so much in this, is it still alright for me to use this?

 

EDIT:

kAZiXd9.gif

 

This is so cool! I can't thank you enough for all this!

I went in and added several more animations.

 

 

 

#==============================================================================
# ** Sprite_TextAnim
#------------------------------------------------------------------------------
#  Sprite subclass for text animations.
#==============================================================================


class Sprite_TextAnim < Sprite
 
  attr_accessor :anim_offset
  attr_accessor :anim_type
  @timer      = false
  @bounce     = 0
  def update
    return unless @anim_offset
    case @anim_type
      when 1
        @anim_offset += 0.115
        self.oy = Math.sin(@anim_offset) * 3
      when 2
        @anim_offset += 0.2
        self.ox = Math.sin(@anim_offset) * 3
        self.oy = Math.cos(@anim_offset) * -3
      when 3
        @anim_offset += 0.15
        self.zoom_x = 1 + Math.sin(@anim_offset) * 0.2
        self.zoom_y = 1 + Math.cos(@anim_offset) * 0.2
      when 4
        if @timer
        self.ox = rand(2) - rand(2)
        self.oy = rand(2) - rand(2)
        end
        @timer = !@timer
      when 5
        @anim_offset += 0.1
        @anim         = @anim_offset * 0.3
        sample  = Math.sin(@anim_offset) * 5
        self.oy = sample.abs
        self.color = Color.new(128 + Math.sin(@anim) * 127,
        128 + Math.sin(@anim + 2*Math::PI/3) * 127,
        128 + Math.sin(@anim + 4*Math::PI/3) * 127,
        255)
      when 6
        @anim_offset += 0.1
        self.ox = Math.sin(@anim_offset) * 3
        self.oy = Math.cos(@anim_offset) * -2
        self.angle = Math.sin(@anim_offset * 0.5) * 10
      else
        return
    end
  end
 
end

#==============================================================================
# ** Window_Message
#------------------------------------------------------------------------------
#  This message window is used to display text.
#==============================================================================

class Window_Message < Window_Base
 
  alias tuckie_wiggly_initialize initialize
  def initialize
    tuckie_wiggly_initialize
    @animchars = []
  end

  #--------------------------------------------------------------------------
  # * Normal Character Processing
  #--------------------------------------------------------------------------
  def process_normal_character(c, pos)
    if @anim_type && @anim_type > 0
      process_anim_character(c, pos)
    else
      super
    end
    wait_for_one_character
  end
 
  #--------------------------------------------------------------------------
  # * Animated Character Processing
  #--------------------------------------------------------------------------
  def process_anim_character(c, pos)
    text_width = text_size(c).width
    letter = Sprite_TextAnim.new(self.viewport)
    bitmap = Bitmap.new(text_width * 2, pos[:height])
    bitmap.font = self.contents.font
    bitmap.draw_text(0, 0, text_width * 2, pos[:height], c)
    letter.bitmap = bitmap
    letter.x = pos[:x] + self.standard_padding
    letter.y = self.y + standard_padding + pos[:y]
    letter.z = self.z + 10
    letter.anim_offset = @animchars.size
    if @anim_type == 5
      letter.anim_offset = 0  
    end
    letter.anim_type = @anim_type
    @animchars.push(letter)
    pos[:x] += text_width
  end
 
  #--------------------------------------------------------------------------
  # * Control Character Processing
  #     code : the core of the control character
  #            e.g. "C" in the case of the control character \C[1].
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_process_escape_character process_escape_character
  def process_escape_character(code, text, pos)
    case code.upcase
    when 'ANI' # Text Animation (by number)
      @anim_type = obtain_escape_param(text)
    when 'OFF' # No Text Animation
      @anim_type = 0
    when 'WAV' # Wave animation
      @anim_type = 1
    when 'SHK' # Shakey animation
      @anim_type = 2
    end
    tuckie_wiggly_process_escape_character(code, text, pos)
  end

  #--------------------------------------------------------------------------
  # * Close Window and Wait for It to Fully Close
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_close_wait close_and_wait
  def close_and_wait
    dispose_text_animation()
    tuckie_wiggly_close_wait()
  end
 
  #--------------------------------------------------------------------------
  # * Free animated text
  #--------------------------------------------------------------------------
  def dispose_text_animation
    @animchars.each do |letter|
      letter.dispose
    end
    @animchars = []
  end
 
  #--------------------------------------------------------------------------
  # * Window Update
  #--------------------------------------------------------------------------  
  alias tuckie_wiggly_update_base update
  def update
    update_text_animation()
    tuckie_wiggly_update_base()
  end
   
  #--------------------------------------------------------------------------
  # * Text Animation Processing
  #--------------------------------------------------------------------------
  def update_text_animation()
    unless @animchars.empty?
      @animchars.each do |letter|
        letter.update
      end
    end
  end
 
end

 

Edited by Tuckie

Share this post


Link to post
Share on other sites

Sure, use it all you want! I like to help!

 

*sprinkles fairy dust on you*

 

You came up with some fun stuff! I wonder if I could change it to let you combine animations? That might be tricky.

Edited by KilloZapit

Share this post


Link to post
Share on other sites

Hmm, that could make some very interesting results.

 

In the meantime, I fixed an issue where text wouldn't clear when a new page was opened. If you had two show text events right after each other, the letters wouldn't clear away. I also changed the rainbow effect so you could make it on any animation, by using \RAN and turning off with \BLN or \OFF.

 

Also, an option to let regular letters drop in on entrance! This does mean that I replaced all characters in the textbox with these bitmaps. \ANI[7] creates characters without animation.

fUhVHEd.gif

 

Just for fun, I tried replicating the paper mario text box using Galv's custom message background script.

PEGk17E.gif

 

I also added an option that extends Galv's script to make the background subtly float, and all the text follows it's movement

in addition to their own animations. You have to put the script under Galv's. Eventually I'd like to extend this to work with RPGMaker's text boxes as well. I'd also like to add a little more control over the icon that pops up when the text box finishes, like putting it in a corner or having it rotate.

I've been updating the code in the spoiler as I go.

 

New edit: I made a lot of additions to process_anim_character() based on my needs, but now decided to move them all to a seperate method for visual clarity.

 

 

#==============================================================================
# ** SETTINGS
#------------------------------------------------------------------------------
#  Currently only a few small settings. Looking to add functionality for
#  simple user-made effects...
#==============================================================================

module WiggleText
 
  #Characters 'drop in' when first drawn.
  DROP_IN     = true
  #Height from where characters drop.
  DROP_HEIGHT = 8
 
  # If using Galv's message background script,
  # This will add a subtle floating effect to the text box, and all
  # characters inside. PLACE THIS SCRIPT BELOW GALV'S MESSAGE BACKGROUND.
  GALV_ANI    = false
end
#==============================================================================
# ** Sprite_TextAnim
#------------------------------------------------------------------------------
#  Sprite subclass for text animations.
#==============================================================================


class Sprite_TextAnim < Sprite
 
  attr_accessor :anim_offset
  attr_accessor :anim_type
  attr_accessor :rainbow
  attr_accessor :rainbow_offset
  attr_accessor :drop
  @timer      = false
  attr_accessor :galv_ani
 
 
  def galv_ani
    if WiggleText::GALV_ANI
      @galv_ani += 0.05
      self.oy = self.oy + Math.sin(@galv_ani) * 3
    end
  end
 
  def update
    return unless @anim_offset
    self.oy = @drop
    @drop -= @drop * 0.16
    if @drop < 0
      @drop = 0
    end
    if @rainbow
      @rainbow_offset += 0.03
      self.color = Color.new(128 + Math.sin(@rainbow_offset) * 127,
        128 + Math.sin(@rainbow_offset + 2*Math::PI/3) * 127,
        128 + Math.sin(@rainbow_offset + 4*Math::PI/3) * 127,
        255)
    end
    case @anim_type
      when 1
        @anim_offset += 0.115
        self.oy = Math.sin(@anim_offset) * 3
        galv_ani()
      when 2
        @anim_offset += 0.2
        self.ox = Math.sin(@anim_offset) * 3
        self.oy = Math.cos(@anim_offset) * -3
        galv_ani()
      when 3
        @anim_offset += 0.15
        self.zoom_x = 1 + Math.sin(@anim_offset) * 0.2
        self.zoom_y = 1 + Math.cos(@anim_offset) * 0.2
        galv_ani()
      when 4
        if @timer
        self.ox = rand(2) - rand(2)
        self.oy = rand(2) - rand(2)
        end
        @timer = !@timer
        galv_ani()
      when 5
        @anim_offset += 0.1
        sample  = Math.sin(@anim_offset) * 5
        self.oy = sample.abs
        galv_ani()
      when 6
        @anim_offset += 0.1
        self.ox = Math.sin(@anim_offset) * 3
        self.oy = Math.cos(@anim_offset) * -2
        self.angle = Math.sin(@anim_offset * 0.5) * 10
        galv_ani()
      when 7
        #no animation
        galv_ani()
      when 8
        @anim_offset -= @anim_offset * 0.04
        self.oy = @anim_offset
      else
        return
    end
  end
 
end

#==============================================================================
# ** Window_Message
#------------------------------------------------------------------------------
#  This message window is used to display text.
#==============================================================================

class Window_Message < Window_Base
 
  alias tuckie_wiggly_initialize initialize
  def initialize
    tuckie_wiggly_initialize
    @animchars = []
    @rainbow = false
    @anim_offset = 0
  end

  #--------------------------------------------------------------------------
  # * Normal Character Processing
  #--------------------------------------------------------------------------
  def process_normal_character(c, pos)
    if @anim_type && @anim_type > 0
      process_anim_character(c, pos)
    else
      @anim_type = 7
      process_anim_character(c, pos)
    end
    wait_for_one_character
  end
 
  #--------------------------------------------------------------------------
  # * Animated Character Processing
  #--------------------------------------------------------------------------
  def process_anim_character(c, pos)
    text_width = text_size(c).width
    letter = Sprite_TextAnim.new(self.viewport)
    bitmap = Bitmap.new(text_width * 2, pos[:height])
    bitmap.font = self.contents.font
    bitmap.draw_text(0, 0, text_width * 2, pos[:height], c)
    letter.bitmap = bitmap
    letter.x = pos[:x] + self.standard_padding
    letter.y = self.y + standard_padding + pos[:y]
    letter.z = self.z + 10
    letter.anim_offset = @animchars.size
    letter.anim_type = @anim_type
    tuckie_extra(letter)
    @animchars.push(letter)
    pos[:x] += text_width
  end
  #--------------------------------------------------------------------------
  # * Animated Character Extra Conditions
  #--------------------------------------------------------------------------
  def tuckie_extra(letter)
    if WiggleText::DROP_IN
      letter.drop = WiggleText::DROP_HEIGHT
    else
      letter.drop = 0
    end  
    if @anim_type == 5
      letter.anim_offset = 0  
    end
    letter.galv_ani = get_galvani
    if @rainbow
      letter.rainbow = true
      letter.rainbow_offset = @animchars.size * 0.5
    end
    if @anim_type == 5
      letter.anim_offset = 0  
    end
    letter.galv_ani = get_galvani
    if @rainbow
      letter.rainbow = true
      letter.rainbow_offset = @animchars.size * 0.5
    end
  end
  #--------------------------------------------------------------------------
  # * Control Character Processing
  #     code : the core of the control character
  #            e.g. "C" in the case of the control character \C[1].
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_process_escape_character process_escape_character
  def process_escape_character(code, text, pos)
    case code.upcase
    when 'ANI' # Text Animation (by number)
      @anim_type = obtain_escape_param(text)
    when 'OFF' # No Text Animation
      @anim_type = 7
      @rainbow = false
    when 'WAV' # Wave animation
      @anim_type = 1
    when 'SHK' # Shakey animation
      @anim_type = 2
    when 'RAN'
      @rainbow = true
    when 'BLN'
      @rainbow = false
    end
    tuckie_wiggly_process_escape_character(code, text, pos)
  end

  #--------------------------------------------------------------------------
  # * Close Window and Wait for It to Fully Close
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_close_wait close_and_wait
  def close_and_wait
    dispose_text_animation()
    tuckie_wiggly_close_wait()
  end
  #--------------------------------------------------------------------------
  # * New Page
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_new_page new_page
  def new_page(*args)
    dispose_text_animation()
    tuckie_wiggly_new_page(*args)
  end
  #--------------------------------------------------------------------------
  # * Free animated text
  #--------------------------------------------------------------------------
  def dispose_text_animation
    @animchars.each do |letter|
      letter.dispose
    end
    @animchars = []
  end
  #--------------------------------------------------------------------------
  # * Galv Animated Textbox
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_create_back_bitmap create_back_bitmap
  def create_back_bitmap
    @anim_offset = 0
    tuckie_wiggly_create_back_bitmap()
  end

  alias tuckie_wiggle_update_back_sprite update_back_sprite
  def update_back_sprite
    if WiggleText::GALV_ANI
      tuckie_update()
    end
    tuckie_wiggle_update_back_sprite
  end

  def get_galvani
    return @anim_offset
  end
  def tuckie_update
    @anim_offset += 0.05
    @bg.oy = Math.sin(@anim_offset) * 3
  end
  #--------------------------------------------------------------------------
  # * Window Update
  #--------------------------------------------------------------------------  
  alias tuckie_wiggly_update_base update
  def update
    update_text_animation()
    tuckie_wiggly_update_base()
  end
  #--------------------------------------------------------------------------
  # * Text Animation Processing
  #--------------------------------------------------------------------------
  def update_text_animation()
    unless @animchars.empty?
      @animchars.each do |letter|
        letter.update
      end
    end
  end
 
end

 

 

Edited by Tuckie

Share this post


Link to post
Share on other sites

Hmmm... Interesting. I am not sure if using sprites for all text all the time is always a good idea or not (it might cause crazy lag), but if it runs fine then that's okay. Maybe if it becomes a problem I can figure out a way to draw it too the bitmap after it finishes dropping. Also you might want to check if galv's script is installed somehow before messing with stuff for it... I donno. I think I might fiddle around with it more later. It's fun! I also have been fiddling with a text sound script for a while. :o

Edited by KilloZapit

Share this post


Link to post
Share on other sites

What do you mean by 'installed'? I didn't have to modify any of galv's script to get that to work, just method aliasing(which is why it has to go under). Performance is definitely a concern. A full page of letters with animation and rainbow dips down to 45 fps. I'm not sure if this is how it works, but could handling the animation with fibers (thus putting it on a new thread?) Improve speed?

 

Text sound is very important, too. Though I have seen a few scripts for that already, and this script works fine with the one I use. If you don't mind me asking, what else would yours do? Maybe better support for switching sound effects?

Share this post


Link to post
Share on other sites

I mean you should make sure it works without galv's scripts too.

 

It doesn't work like that. Fibers are not the same thing as threads. Threads are actually full extra processes, fibers are only for flow control and nothing else. You can't do two things at once with a fiber, you can only interrupt the flow and resume it later. I am not sure RGSS3 even supports threads, and even if it does they are really really hard to use.

 

My text sound script has random pitches and multiple sounds, but I haven't done switching sounds mid-textbox yet (right now it chooses the sound before a text box)... maybe I should?

Edited by KilloZapit

Share this post


Link to post
Share on other sites

Okay, I must have read incorrectly into fibers then.

The script doesn't crash even without galvs script, I tested that. It just seems to give all the default characters a slow waving animation. That's also why I made the option in there.

 

I love random pitch variance for the sounds; I had to add it in to the one I currently use, and it would be cool to change sound mid message- to give accent to a specific word or something. I've also seen one where there's a bit of randomness to whether or not it plays sound at all, I think that makes it feel a little more "speech" ey.

Share this post


Link to post
Share on other sites

Looking more into performance, I thought I'd mention that I tested this system in MKXP (Open source rgss3 implementation) which renders via OpenGL has no performance issues whatsoever.

One way I'm thinking about increasing speed is to potentially "pre-render" the sine-waves on initialization. So instead of calculating 100+ sin functions each frame each character just advances to the next entry on an array?

 

In the meantime I fixed a bug where letters would not be deleted when the name-entry screen was opened.

 

 

 

#==============================================================================
# ** SETTINGS
#------------------------------------------------------------------------------
#  Currently only a few small settings. Looking to add functionality for
#  simple user-made effects...
#==============================================================================

module WiggleText
 
  #Characters 'drop in' when first drawn.
  DROP_IN     = true
  #Height from where characters drop.
  DROP_HEIGHT = 8
 
  # If using Galv's message background script,
  # This will add a subtle floating effect to the text box, and all
  # characters inside. PLACE THIS SCRIPT BELOW GALV'S MESSAGE BACKGROUND.
  GALV_ANI    = true
end
#==============================================================================
# ** Sprite_TextAnim
#------------------------------------------------------------------------------
#  Sprite subclass for text animations.
#==============================================================================


class Sprite_TextAnim < Sprite
 
  attr_accessor :anim_offset
  attr_accessor :anim_type
  attr_accessor :rainbow
  attr_accessor :rainbow_offset
  attr_accessor :drop
  @timer      = false
  attr_accessor :galv_ani
 
 
  def galv_ani
    if WiggleText::GALV_ANI
      @galv_ani += 0.05
      self.oy = self.oy + Math.sin(@galv_ani) * 3
    end
  end
 
  def update
    return unless @anim_offset
    self.oy = @drop
    @drop -= @drop * 0.16
    if @drop < 0
      @drop = 0
    end
    if @rainbow
      @rainbow_offset += 0.03
      self.color = Color.new(128 + Math.sin(@rainbow_offset) * 127,
        128 + Math.sin(@rainbow_offset + 2*Math::PI/3) * 127,
        128 + Math.sin(@rainbow_offset + 4*Math::PI/3) * 127,
        255)
    end
    case @anim_type
      when 1
        @anim_offset += 0.115
        self.oy = Math.sin(@anim_offset) * 3
        galv_ani()
      when 2
        @anim_offset += 0.2
        self.ox = Math.sin(@anim_offset) * 3
        self.oy = Math.cos(@anim_offset) * -3
        galv_ani()
      when 3
        @anim_offset += 0.15
        self.zoom_x = 1 + Math.sin(@anim_offset) * 0.2
        self.zoom_y = 1 + Math.cos(@anim_offset) * 0.2
        galv_ani()
      when 4
        if @timer
        self.ox = rand(2) - rand(2)
        self.oy = rand(2) - rand(2)
        end
        @timer = !@timer
        galv_ani()
      when 5
        @anim_offset += 0.1
        sample  = Math.sin(@anim_offset) * 5
        self.oy = sample.abs
        galv_ani()
      when 6
        @anim_offset += 0.1
        self.ox = Math.sin(@anim_offset) * 3
        self.oy = Math.cos(@anim_offset) * -2
        self.angle = Math.sin(@anim_offset * 0.5) * 10
        galv_ani()
      when 7
        #no animation
        galv_ani()
      when 8
        @anim_offset -= @anim_offset * 0.04
        self.oy = @anim_offset
      else
        return
    end
  end
 
end

#==============================================================================
# ** Window_Message
#------------------------------------------------------------------------------
#  This message window is used to display text.
#==============================================================================

class Window_Message < Window_Base
 
  alias tuckie_wiggly_initialize initialize
  def initialize
    tuckie_wiggly_initialize
    @animchars = []
    @rainbow = false
    @anim_offset = 0
  end

  #--------------------------------------------------------------------------
  # * Normal Character Processing
  #--------------------------------------------------------------------------
  def process_normal_character(c, pos)
    if @anim_type && @anim_type > 0
      process_anim_character(c, pos)
    else
      @anim_type = 7
      process_anim_character(c, pos)
    end
    wait_for_one_character
  end
 
  #--------------------------------------------------------------------------
  # * Animated Character Processing
  #--------------------------------------------------------------------------
  def process_anim_character(c, pos)
    text_width = text_size(c).width
    letter = Sprite_TextAnim.new(self.viewport)
    bitmap = Bitmap.new(text_width * 2, pos[:height])
    bitmap.font = self.contents.font
    bitmap.draw_text(0, 0, text_width * 2, pos[:height], c)
    letter.bitmap = bitmap
    letter.x = pos[:x] + self.standard_padding
    letter.y = self.y + standard_padding + pos[:y]
    letter.z = self.z + 10
    letter.anim_offset = @animchars.size
    letter.anim_type = @anim_type
    tuckie_extra(letter)
    @animchars.push(letter)
    pos[:x] += text_width
  end
  #--------------------------------------------------------------------------
  # * Animated Character Extra Conditions
  #--------------------------------------------------------------------------
  def tuckie_extra(letter)
    if WiggleText::DROP_IN
      letter.drop = WiggleText::DROP_HEIGHT
    else
      letter.drop = 0
    end  
    if @anim_type == 5
      letter.anim_offset = 0  
    end
    letter.galv_ani = get_galvani
    if @rainbow
      letter.rainbow = true
      letter.rainbow_offset = @animchars.size * 0.5
    end
    if @anim_type == 5
      letter.anim_offset = 0  
    end
    letter.galv_ani = get_galvani
    if @rainbow
      letter.rainbow = true
      letter.rainbow_offset = @animchars.size * 0.5
    end
  end
  #--------------------------------------------------------------------------
  # * Control Character Processing
  #     code : the core of the control character
  #            e.g. "C" in the case of the control character \C[1].
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_process_escape_character process_escape_character
  def process_escape_character(code, text, pos)
    case code.upcase
    when 'ANI' # Text Animation (by number)
      @anim_type = obtain_escape_param(text)
    when 'OFF' # No Text Animation
      @anim_type = 7
      @rainbow = false
    when 'WAV' # Wave animation
      @anim_type = 1
    when 'SHK' # Shakey animation
      @anim_type = 2
    when 'RAN'
      @rainbow = true
    when 'BLN'
      @rainbow = false
    end
    tuckie_wiggly_process_escape_character(code, text, pos)
  end

  #--------------------------------------------------------------------------
  # * Close Window and Wait for It to Fully Close
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_close_wait close_and_wait
  def close_and_wait
    dispose_text_animation()
    tuckie_wiggly_close_wait()
  end
  #--------------------------------------------------------------------------
  # * Close Window and Wait for It to Fully Close
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_dispose dispose
  def dispose
    dispose_text_animation()
    tuckie_wiggly_dispose()
  end
  #--------------------------------------------------------------------------
  # * New Page
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_new_page new_page
  def new_page(*args)
    dispose_text_animation()
    tuckie_wiggly_new_page(*args)
  end
  #--------------------------------------------------------------------------
  # * Free animated text
  #--------------------------------------------------------------------------
  def dispose_text_animation
    @animchars.each do |letter|
      letter.dispose
    end
    @animchars = []
  end
  #--------------------------------------------------------------------------
  # * Galv Animated Textbox
  #--------------------------------------------------------------------------
  alias tuckie_wiggly_create_back_bitmap create_back_bitmap
  def create_back_bitmap
    @anim_offset = 0
    tuckie_wiggly_create_back_bitmap()
  end

  alias tuckie_wiggle_update_back_sprite update_back_sprite
  def update_back_sprite
    if WiggleText::GALV_ANI
      tuckie_update()
    end
    tuckie_wiggle_update_back_sprite
  end

  def get_galvani
    return @anim_offset
  end
  def tuckie_update
    @anim_offset += 0.05
    @bg.oy = Math.sin(@anim_offset) * 3
  end
  #--------------------------------------------------------------------------
  # * Window Update
  #--------------------------------------------------------------------------  
  alias tuckie_wiggly_update_base update
  def update
    update_text_animation()
    tuckie_wiggly_update_base()
  end
  #--------------------------------------------------------------------------
  # * Text Animation Processing
  #--------------------------------------------------------------------------
  def update_text_animation()
    unless @animchars.empty?
      @animchars.each do |letter|
        letter.update
      end
    end
  end
 
end

 

 

Share this post


Link to post
Share on other sites

Well, I am not sure if the problem is the sine waves or just having lots of sprite objects. You could try a fixed point sine table if you wanted though. I was wondering if there is some good way to render the sprite and delete it after it gets dropped in.

Share this post


Link to post
Share on other sites

Thank you for such an interesting effect for text drawing!

These effects are those I also want to realize in recent days.

First I saw it in a new indie game named "Lion's Song"

I am an RPGmaker user from Chinese bbs “rpg.blue” which is used to name "66RPG".

May I translate your scripts to Chinese in "rpg.blue" for Chinese users who may be interested in it?

Author's name and copyright will be also posted for addiction.

Thank you so much again!

 

Share this post


Link to post
Share on other sites

Hey there,

really nice work so far!

 

I created a FF7 Limit break system in my project and made it that every text character have

a differnet color and the colors move from left to right.

But your gradient text looks so much better!

PEGk17E.gif

I wonder if i could use it and if so does it affect performance really hard to have just the gradient text?

Here is my code, i know really novice but hey it works for me. xD

Spoiler

#==============================================================================
# ** Window_ActorLimit
#------------------------------------------------------------------------------
#  This window is used to show actor command "Limit".
#==============================================================================

class Window_ActorLimit < Window_Base
  #--------------------------------------------------------------------------
  # * Initialize
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height)
    super(x, y, width, height)
    self.z = 500
    self.opacity = 0
    self.back_opacity = 0
    self.openness = 0
    @actor = nil
    @frame = nil
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    super
    return unless @frame
    return unless @actor
    return unless @actor.tp == 100
    refresh
    @frame += 1
    @frame = 0 if @frame == 50
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    return unless @actor
    return unless @actor.tp == 100
    case @frame
    when 0
      draw_limit(0)
    when 10
      draw_limit(1)
    when 20
      draw_limit(2)
    when 30
      draw_limit(3)
    when 40
      draw_limit(4)
    end
  end
  #--------------------------------------------------------------------------
  # * Draw Limit text
  #--------------------------------------------------------------------------
  def draw_limit(id)
    contents.clear
    c1 = "\\C[2]"
    c2 = "\\C[1]"
    c3 = "\\C[27]"
    c4 = "\\C[14]"
    c5 = "\\C[3]"
    case id
    when 0
      text = c1 + "L" + c2 + "i" + c3 + "m" + c4 + "i" + c5 + "t"
    when 1
      text = c5 + "L" + c1 + "i" + c2 + "m" + c3 + "i" + c4 + "t"
    when 2
      text = c4 + "L" + c5 + "i" + c1 + "m" + c2 + "i" + c3 + "t"
    when 3
      text = c3 + "L" + c4 + "i" + c5 + "m" + c1 + "i" + c2 + "t"
    when 4
      text = c2 + "L" + c3 + "i" + c4 + "m" + c5 + "i" + c1 + "t"
    end
    draw_text_ex(4, 0, text)
  end
  #--------------------------------------------------------------------------
  # * Setup
  #--------------------------------------------------------------------------
  def setup(actor)
    @actor = actor
    @frame = 0
    refresh
    open
  end
  #--------------------------------------------------------------------------
  # * Close Window
  #--------------------------------------------------------------------------
  def close
    super
    contents.clear
    @actor = nil
    @frame = nil
  end
end

 

 

Edited by buddysievers

Share this post


Link to post
Share on other sites
On 12/1/2017 at 7:00 AM, buddysievers said:

Hey there,

really nice work so far!

 

I created a FF7 Limit break system in my project and made it that every text character have

a differnet color and the colors move from left to right.

But your gradient text looks so much better!

PEGk17E.gif

I wonder if i could use it and if so does it affect performance really hard to have just the gradient text?

Here is my code, i know really novice but hey it works for me. xD

  Reveal hidden contents


#==============================================================================
# ** Window_ActorLimit
#------------------------------------------------------------------------------
#  This window is used to show actor command "Limit".
#==============================================================================

class Window_ActorLimit < Window_Base
  #--------------------------------------------------------------------------
  # * Initialize
  #--------------------------------------------------------------------------
  def initialize(x, y, width, height)
    super(x, y, width, height)
    self.z = 500
    self.opacity = 0
    self.back_opacity = 0
    self.openness = 0
    @actor = nil
    @frame = nil
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    super
    return unless @frame
    return unless @actor
    return unless @actor.tp == 100
    refresh
    @frame += 1
    @frame = 0 if @frame == 50
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    return unless @actor
    return unless @actor.tp == 100
    case @frame
    when 0
      draw_limit(0)
    when 10
      draw_limit(1)
    when 20
      draw_limit(2)
    when 30
      draw_limit(3)
    when 40
      draw_limit(4)
    end
  end
  #--------------------------------------------------------------------------
  # * Draw Limit text
  #--------------------------------------------------------------------------
  def draw_limit(id)
    contents.clear
    c1 = "\\C[2]"
    c2 = "\\C[1]"
    c3 = "\\C[27]"
    c4 = "\\C[14]"
    c5 = "\\C[3]"
    case id
    when 0
      text = c1 + "L" + c2 + "i" + c3 + "m" + c4 + "i" + c5 + "t"
    when 1
      text = c5 + "L" + c1 + "i" + c2 + "m" + c3 + "i" + c4 + "t"
    when 2
      text = c4 + "L" + c5 + "i" + c1 + "m" + c2 + "i" + c3 + "t"
    when 3
      text = c3 + "L" + c4 + "i" + c5 + "m" + c1 + "i" + c2 + "t"
    when 4
      text = c2 + "L" + c3 + "i" + c4 + "m" + c5 + "i" + c1 + "t"
    end
    draw_text_ex(4, 0, text)
  end
  #--------------------------------------------------------------------------
  # * Setup
  #--------------------------------------------------------------------------
  def setup(actor)
    @actor = actor
    @frame = 0
    refresh
    open
  end
  #--------------------------------------------------------------------------
  # * Close Window
  #--------------------------------------------------------------------------
  def close
    super
    contents.clear
    @actor = nil
    @frame = nil
  end
end

 

 

aaaaaaaaaa its been like forever since i've even been on here
ive updated this a few times since i last posted here so heres a pastebin link to that or whatever

 

it might be kind of hard to implement the rainbow text effect I use with how you draw the text. what makes it easy for me to do all these wacky effects is by drawing out each letter as its own object, which meant rewriting the textbox code to place each letter one by one and set up variables that control what effects each letter has. so if you wanted to do what i do you'd need to use a method to parse the text that sets up all the objects in position etc. look around line ~214 in that pastebin generally for what does that.

the actual rainbow effect is pretty simple. im just using the bitmap color function where i use 3 sinewaves to set the R,G,B values of otherwise white text. each letter has a time value that goes inside of the Math.sin() that is slightly different from the last which is why each is a different color. heres what i do for that:
 

self.color = Color.new(128 + Math.sin(@time) * 127, #R value
        128 + Math.sin(@time + 2*Math::PI/3) * 127, #G value
        128 + Math.sin(@time + 4*Math::PI/3) * 127, #B value
        255) #Alpha
#you probably wanna remove those comments before you put this in ur code

if you just wanted to do rainbow effect and only on a few letters it shouldn't really have any performance effects. honestly the whole text animation script isnt that laggy. hope this helps?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×