Envision, Create, Share

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

Text Cache

Atoa

Member

Text Cache
by Atoa



Scripts RGSS, Resources, Tutorials and Translations by Atoa is licensed under a
Creative Commons Atribuição-Uso Não-Comercial-Compartilhamento pela mesma Licença 2.5 Brasil License.
Permissions beyond the scope of this license may be available at Santuário RPG Maker


Introduction

This script has the objective of storing text bitmap objects in cache.
By deafult, the RPG Maker draw each character individually from scratch, even if the same character is repeated frequently.
This make bitmap.draw_text really slow.

This script store the character bitmap on cache at the first it's drawn, and then use an clone of that bitmap if it's needed again

The main objective of this script is reduce the lag caused by windows that are updated constantly or windows with really long text (like an item window with 400 items xD)

The script has one drawback: if the text is bigger than the width set for the draw_text, it won't be streched to fit the smaller space.

Screenshots

This is an screen of an "HUD" with more than 300 character being refreshed every frame, withou the script, take a look at the FPS:


This is the same "HUD" refreshed every frame, the FBS is greatly rised:



How to Use

Paste the code above main

You can clean the cache with an 'script call' and the code clear_text_cache


Script
Code:
#==============================================================================

# Text Cache

# by atoa

#==============================================================================

# This script has the objective of storing text bitmap objects in cache.

# By deafult, the RPG Maker draw each character individually from 

# scratch, even if the same character is repeated frequently.

# This make bitmap.draw_text really slow.

#

# This script store the character bitmap on cache at the first it's drawn, 

# and then use an clone of that bitmap if it's needed again

#

# The main objective of this script is reduce the lag caused by windows

# that are updated constantly or windows with really long text (like an 

# item window with 400 items xD)

#

# The script has one drawback: if the text is bigger than the width set 

# for the draw_text, it won't be streched to fit the smaller space.

#==============================================================================

 

#==============================================================================

# ■ Bitmap

#------------------------------------------------------------------------------

# Classe that handles bitmaps

#==============================================================================

 

class Bitmap

  #------------------------------------------------------------------------------

  # Draw text

  #     x      : Text Coord X or text rect

  #     y      : Text Coord y or text sting

  #     width  : Text width or text align

  #     height : Text height

  #     str    : Text string

  #     align  : Text align

  #------------------------------------------------------------------------------

  alias text_cache_draw_text draw_text if !method_defined?(:text_cache_draw_text)

  def draw_text(x, y, width = 0, height = 0, str = '', align = 0)

    case x

    when Numeric

      adj = align == 0 ? 0 : align == 1 ? (width / 2) - (text_size(str).width / 2) : width  - text_size(str).width

      i = 0   

      for digit in str.to_s.split('')

        bitmap = check_bitmap(digit)

        blt(adj + x + i, y + 4, bitmap[0], bitmap[1])

        i += bitmap[0].width - 2

      end

    when Rect

      rect  = x

      str   = y

      align = width

      adj = align == 0 ? 0 : align == 1 ? (rect.width / 2) - (text_size(str).width / 2) : rect.width  - text_size(str).width

      i = 0   

      for digit in str.to_s.split('')

        bitmap = check_bitmap(digit)

        blt(adj + rect.x + i, rect.y + 4, bitmap[0], bitmap[1])

        i += bitmap[0].width - 2

      end

    end

  end

  #------------------------------------------------------------------------------

  # Check if bitmap is areay in cache

  #   digit : digit to be drawn

  #------------------------------------------------------------------------------

  def check_bitmap(digit)

    $text_cache ||= {}

    color = [font.color.red, font.color.green, font.color.blue, font.color.alpha]

    key = [digit, color, font.size, font.name]

    if $text_cache[key].nil? or $text_cache[key][0].disposed?

     width = text_size(digit).width + 2

      height = text_size(digit).height + 2

      b = Bitmap.new(width, height)

      $text_cache[key] = [b, b.rect]

      b.font.name = font.name

      b.font.size = font.size

      b.font.color.set(color[0], color[1], color[2], color[3])

      b.text_cache_draw_text(0, 0, width, height, digit)

    end

    return $text_cache[key]

  end

end

 

#==============================================================================

# ■ Object

#------------------------------------------------------------------------------

# All classes inherit methods from this class

#==============================================================================

 

class Object

  #------------------------------------------------------------------------------

  # clear text cache

  #------------------------------------------------------------------------------

  def clear_text_cache

    $text_cache ||= {}

    for key in $text_cache.key

      $text_cache[key].dispose

    end

    $text_cache.clear

  end

end

Credits and Thanks
  • By Atoa
 
Considering the structure of RGSS, this really is a needed script... I've never got the idea to do anything like it, but now that I see it, it's like a very simple idea that you'd think someone would've done before... (especially as font drawing is one of the laggiest aspects of RGSS).

Other than that, while not looking at your code much as I'm rather sleepy, I saw you spelled class Object wrong... guess you didn't clear the cache too often now, did you? :p
And yeah, actually, what you noted down as a drawback, I actually think is a good thing, as features encouraging lazy design work (such as the narrow-to-fit feature that's there by default) aren't really needed in my opinion...

Keep up the good work!
 
Nice one, especially because it's only that short :)
Still, you could make it slightly faster:
Code:
  def check_bitmap(digit)

    $text_cache ||= {}

    color = [font.color.red, font.color.green, font.color.blue, font.color.alpha]

    key = [digit, color, font.size, font.name]

    if !$text_cache.has_key?(key)

     width = text_size(digit).width + 2

      height = text_size(digit).height + 2

      b = Bitmap.new(width, height)

      $text_cache[key] = [b, b.rect]

      b.font.name = font.name

      b.font.size = font.size

      b.font.color.set(color[0], color[1], color[2], color[3])

      b.text_cache_draw_text(0, 0, width, height, digit)

    end

    return $text_cache[key]

  end
 
does this works for a moving-bitmap (like the 'damage number', for example)?
how about for a bitmap thats constatly changing string content?

thank you
 

Atoa

Member

@kaB00M
It works for every bitmap generated by bitmap.draw_text, so the default rmxp damage pop up is included.

how about for a bitmap thats constatly changing string content?
that one i didn't get, an bitmap that change strings?
 
Netplay users are going to love you for this as the chat window is probably the laggiest feature due to long strings of text constantly updating.

Great work.

(While I know you have explicitly said you will not allow commercial use from your license, so I won't be using it, this has nonetheless given me ideas of my own for reducing lag, so thank you.)
 

Atoa

Member

@mouse
Waiver — Any of the above conditions can be waived if you get permission from the copyright holder.
So if I allow, this script can be used in commercial projects also, normally all i ask is one free copy for me xD
 
I'm trying to understand this code, so I can improve the performance of my coding in general.
So basically, what makes this so much faster is the 're-use' of this block?

if !$text_cache.has_key?(key)
width = text_size(digit).width + 2
height = text_size(digit).height + 2
b = Bitmap.new(width, height)
$text_cache[key] = [b, b.rect]
b.font.name = font.name
b.font.size = font.size
b.font.color.set(color[0], color[1], color[2], color[3])
b.text_cache_draw_text(0, 0, width, height, digit)
end

So it can be said that 8 lines of code in constant use make difference?
Or is it the original draw_text method thats time consuming?
 
ATOA, i must say that in caps because, i made a hud i freaking loved a while back, but due to all the redrawing of the hud and text box and other windows the player could open my game simply couldn't handle it,i added your script and it worked without lagging at all :) thanks a billion!
 

arev

Sponsor

Impressive enhancement. It's a lot better than checking if any of the hud's texts have changed since the last frame.
 

Thank you for viewing

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

Discord

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

Content

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