Optimized Way to Draw Text

Discussion in 'Learning Ruby and RGSSx' started by Rikifive, Sep 5, 2016.

  1. Rikifive

    Rikifive Bringer of Happiness Veteran

    Messages:
    1,442
    Likes Received:
    676
    Location:
    Poland
    First Language:
    Polish
    Primarily Uses:
    Other
    Hello everybody!
     
    I want to draw a number, that will have to be updated each frame from time to time.
    Now I'm wondering on how I should approach this.
    While I might know the possible solution, I wanted to ask for advice, to be sure, that things will be done correctly.
     
    What I want is to basically make a sprite, that will be showing a number like:
    24%
    67%
    etc.
    Now that value may change each frame, for example dropping from 100% to 0%.
     
    Now I could make that using window, but redrawing that all each frame would be destructive.
     
    I could also make a bitmap and draw the text directly in here, though I found that note in Ace's help file regarding the draw_text method:

    So I guess I should find something else then, right?
     
    So that leaves me the 'blt' method.
    To be honest I haven't used that much and though I believe I could find as way to make it work properly ~ I think there's most likely a pretty easy way to achieve that isn't it? So before I'll overcomplicate things, may I ask for some guide/tips/suggestions?
     
    or I could make multiple sprites for each number and use src_rect ~ but I believe that would not be right, right?
     
     
    Thank you! (=
     
    #1
  2. Ossra

    Ossra Formerly Exhydra Veteran

    Messages:
    646
    Likes Received:
    492
    First Language:
    English
    Primarily Uses:
    RMMV
    You could create ten bitmaps with zero through nine, then block transfer the numbers you need into a sprite or onto another bitmap. Although a question I have is ... why the window or such being redrawn each frame? Is it not possible to check to see if the percent has been changed before performing the redraw? It may be easier to restrict when the window or sprite is being redrawn.


    EDIT: Having multiple sprites for each digit might work best, if that is the way it has to go. That would skip draw text and block transfer. If there are multiple percent tickers, then you could create one set of bitmaps which the digit sprites would then use ... lowering the amount of times draw text would be called even further.
     
    Last edited by a moderator: Sep 5, 2016
    #2
  3. Rikifive

    Rikifive Bringer of Happiness Veteran

    Messages:
    1,442
    Likes Received:
    676
    Location:
    Poland
    First Language:
    Polish
    Primarily Uses:
    Other
    Mhm I see..


    Am I the only RPG Maker user that needs to update some stuff each frame? x3


    Don't get me wrong ~ I'm just kidding.


    It's not the case, but as for examples I could refer to:


    - making a timer that shows milliseconds - would that need to be updated each frame? Yes.


    - making an altimeter, that shows height and stuff - if I'd be falling down very fast, would that need to be updated each frame? Yes.


    - making an arcade game, where there are tons of projectiles and enemies- if I'd be getting score extremely fast, would that need to be updated each frame? Yes.


    Now my case:


    I'm making options scene, where you can set the volume of things. It shows the %rate of the volume and it needs to be updated (sometimes each frame) when it's changed/dragged:


    [​IMG]


    Currently I've made it in the easy way - make sprite for each value and clear&redraw text each time it is changed.


    While it doesn't cause noticeable framedrop nor anything, I think I should be learning making the thing in the proper way.


    Hope it explains it better. x3


    Thanks! (=
     
    Last edited by a moderator: Sep 5, 2016
    #3
  4. Ossra

    Ossra Formerly Exhydra Veteran

    Messages:
    646
    Likes Received:
    492
    First Language:
    English
    Primarily Uses:
    RMMV


    For the situation, I think you are on the 'proper' path. I mean, you could generate zero through nine sprite digits as I explained in my edit above, then scrunch the two digits and the percent sign together to reduce the amount of redraws. But for the menu, I would say you are fine. There will be no noticeable drop in framerate and arranging multiple sprites in the proper order is more trouble than it is worth. Maybe if there were multiple health bars with percent tickers constantly getting jiggled around on a very active, crowded screen ... then I would say move toward sprites versus redraws. 
     
    #4
    Rikifive likes this.
  5. Rikifive

    Rikifive Bringer of Happiness Veteran

    Messages:
    1,442
    Likes Received:
    676
    Location:
    Poland
    First Language:
    Polish
    Primarily Uses:
    Other
    Mhm, I understand what you mean. That makes sense.


    Your suggestion is exactly what I did in another project - though there I had to draw only two digits ~ I might have to draw more of them in future (for example in battle system or somewhere esle), so I was thinking if there would be an easier way to achieve that. =P


    Maybe making a class for that would make it neater? I'll be trying few things in future..


    ~ Thanks for help.
     
    #5
  6. Ossra

    Ossra Formerly Exhydra Veteran

    Messages:
    646
    Likes Received:
    492
    First Language:
    English
    Primarily Uses:
    RMMV
    I'm not sure if this will help -- maybe it will give you some ideas -- but here is what I did when I needed multiple sprite buttons in a name input script. Basically, yes ... a separate class is the way to go. 


    [​IMG]




    Each button comes from a custom class, loading a bitmap from a pre-made button graphic file. I have another version where I created the button bitmap on-the-fly using draw rect and draw text, but I can't find the code.


    [​IMG]





    Spoiler





    # +--------------------------------------------------------------------------¦¦
    # ¦ [Class] NS::InputButton
    # +--------------------------------------------------------------------------¦¦

    class NS::InputButton

    # +------------------------------------------------------------------------¦?
    # ? [Method] Initialize
    # +------------------------------------------------------------------------¦?
    def initialize(button, x, y)

    @button = button
    @color_on = Color.new(0,0,0,125)
    @color_off = Color.new
    bitmap = Cache.system('Buttons')
    button_bitmap = Bitmap.new(24, 24)

    button_bitmap.blt(0, 0, bitmap, button_rect(button))

    @sprite = Sprite.new
    @sprite.bitmap = button_bitmap

    @sprite.x, @sprite.y, @x, @y = x, y, x, y
    @sprite.z = 200

    bitmap.dispose

    end

    # +------------------------------------------------------------------------¦?
    # ? [Method] Dispose
    # +------------------------------------------------------------------------¦?
    def dispose
    @sprite.dispose
    end

    # +------------------------------------------------------------------------¦?
    # ? [Method] Update Press
    # +------------------------------------------------------------------------¦?
    def update_press
    if Input.press?(@button)
    @sprite.y = (@y + 2)
    @sprite.color = @color_on
    else
    @sprite.y = @y
    @sprite.color = @color_off
    end
    end

    # +------------------------------------------------------------------------¦?
    # ? [Method] Change Button Opacity
    # +------------------------------------------------------------------------¦?
    def opacity=(opacity)
    @sprite.opacity = opacity
    end

    # +------------------------------------------------------------------------¦?
    # ? [Method] Get Button Rect
    # +------------------------------------------------------------------------¦?
    def button_rect(button)
    button_list = [ :A, :B, :C, :L,
    :X, :Y, :Z, :R ]

    y = ([1, button_list.index(button)].max / 4).floor
    x = (button_list.index(button) - (y * 4))

    return Rect.new((x * 24), (y * 24), 24, 24)
    end

    end # ‹‹ NS::InputButton



    In a later project, I refined the class to what it should have been before (a sprite versus storing a sprite in a variable).


    [​IMG]



    Code:
    
    
    #==============================================================================
    # ** Sprite_Button
    #==============================================================================
    
    class Sprite_Button < Sprite
    
      #--------------------------------------------------------------------------
      # * Object Initialization
      #--------------------------------------------------------------------------
      def initialize(window, button, x, y)
        super(window.viewport)
        
        @button         = button
        bitmap          = Cache.system('Menu-Buttons')
        button_bitmap   = Bitmap.new(16, 13)
    
        button_bitmap.blt(0, 0, bitmap, button_rect(button))
    
        self.bitmap = button_bitmap
        
        bitmap.dispose
        
        @sx, @sy = x, y
        self.x, self.y = x, y
        self.z = window.z + 1
      end
      
      #--------------------------------------------------------------------------
      # * Frame Update
      #--------------------------------------------------------------------------
      def update
        super
        
        update_press
      end
    
      #--------------------------------------------------------------------------
      # * Update Press
      #--------------------------------------------------------------------------
      def update_press
        if Input.press?(@button)
          self.y = (@sy + 2)
        else
          self.y = @sy
        end
      end
      
      #--------------------------------------------------------------------------
      # * Get Button Rect
      #--------------------------------------------------------------------------
      def button_rect(button)
        button_list = [ :L, :R, :Y, :Z ]
    
        y = ([1, button_list.index(button)].max / 4).floor
        x = (button_list.index(button) - (y * 4))
    
        return Rect.new((x * 16), (y * 13), 16, 13)
      end
      
    end # Sprite_Button
     
    Last edited by a moderator: Sep 5, 2016
    #6

Share This Page