Main Menu
  • Welcome to The RPG Maker Resource Kit.

[VX/Ace] draw_face and bitmap.dispose

Started by cozziekuns, February 11, 2013, 12:12:06 AM

0 Members and 1 Guest are viewing this topic.

cozziekuns

So I recently learned the hard way that repeated dispose calls for bitmaps is a great way to lag your project like hell. So, why does Window_Base's draw_face method have a bitmap.dispose call when draw_icon and draw_character don't?

The three methods in question:


class Window_Base

  def draw_icon(icon_index, x, y, enabled = true)
    bitmap = Cache.system("Iconset")
    rect = Rect.new(icon_index % 16 * 24, icon_index / 16 * 24, 24, 24)
    contents.blt(x, y, bitmap, rect, enabled ? 255 : translucent_alpha)
  end

  def draw_face(face_name, face_index, x, y, enabled = true)
    bitmap = Cache.face(face_name)
    rect = Rect.new(face_index % 4 * 96, face_index / 4 * 96, 96, 96)
    contents.blt(x, y, bitmap, rect, enabled ? 255 : translucent_alpha)
    bitmap.dispose # The line in question
  end

  def draw_character(character_name, character_index, x, y)
    return unless character_name
    bitmap = Cache.character(character_name)
    sign = character_name[/^[\!\$]./]
    if sign && sign.include?('$')
      cw = bitmap.width / 3
      ch = bitmap.height / 4
    else
      cw = bitmap.width / 12
      ch = bitmap.height / 8
    end
    n = character_index
    src_rect = Rect.new((n%4*3+1)*cw, (n/4*4)*ch, cw, ch)
    contents.blt(x - cw / 2, y - ch, bitmap, src_rect)
  end

end

TDS

Could be a remnant of the VX method when they started to work on RGSS3. I've noticed a few other things in certain classes that do not accomplish anything, but were in the code in VX.


  def draw_face(face_name, face_index, x, y, size = 96)
    bitmap = Cache.face(face_name)
    rect = Rect.new(0, 0, 0, 0)
    rect.x = face_index % 4 * 96 + (96 - size) / 2
    rect.y = face_index / 4 * 96 + (96 - size) / 2
    rect.width = size
    rect.height = size
    self.contents.blt(x, y, bitmap, rect)
    bitmap.dispose
  end


I could be wrong though, but from my understanding of how the Cache module works there doesn't seem to be a reason to dispose of it since it would be used a lot in other parts and disposing and reloading defeats the purpose of Cache.

And removing the line does not seem to affect how the game works either.


modern algebra

#2
Disposing the pictures is not itself laggy; the lag is likely generated by repeatedly retrieiving the bitmap from the picture file (CPU memory). Because it takes so much time to load graphics that way, the Cache module ordinarily stores them in RAM for quick retrieval.

I assume that the iconset and characters aren't disposed because it makes sense to keep that in memory. After all, icons are used frequently enough that retrieving the huge IconSet graphic from CPU memory all the time would cause lag. Similarly, the character bitmap has to be kept in RAM in order to animate the sprites. The decision not to dispose after drawing it in a window was probably based on the assumption that any characters being drawn in a window are also likely contained in a sprite as well. You wouldn't want a situation where you drew a character on a window in Scene_Map, only to then have that bitmap disposed and have every sprite using that characterset on the map disappear.

Facesets, on the other hand, are typically large files and they are used very infrequently. By default, they are only drawn in the menu and in message windows, and in each circumstances there is not much of a penalty in loading from the CPU (at most, there would only be a little bit of lag when first loading the menu, and the message window is refreshed infrequently enough that it likely makes little difference. As such, the speed increase from storing the pictures in RAM is negligible (by default), and so the programmers likely decided that it wasn't worth the space. That's likely why they chose to dispose facesets, but not the other graphics you mention.

If you're writing a script where it makes sense to use RAM to store the pictures however, and it sounds like you are, then by all means create a method which does not dispose the faceset. Given their size, however, you should eventually dispose them once it is no longer worthwhile to keep them in RAM (for instance, when you exit the scene).