[XP] ATB Script - Need a better way to do HP Bars

Started by Heretic86, April 15, 2012, 07:54:31 pm

Previous topic - Next topic

Heretic86

Posted this same question on another forum, but hey, Im impatient.

The script I have draws some nice looking HP Bars, but they function like frozen dog snot at the north pole in the middle of winter.  Basically, when the Interpreter is running, performance goes way way way south.  Seems to only occur when the Interpreter is running however.  So during a battle, if one of the characters says something, or performs some sort of Event Action, I get lag out the wazoo.  Wazoo.debug failed to correct the issue, and Wazoo.dispose leaves me with no purdy HP Bars.

Script I am running is called ATB: http://www.775.net/~heretic/downloads/rmxp/cat.php around line 1420 or so.

What it looks like is happening is that a non object window is being displayed each and every frame.  I dont mind doing a total rewrite of this section as long as it doesnt cause lag.  And the lag is obviously coming from drawing the HP / SP / CP / Shadowed Text each and every time.  How can I best do this efficiently so it doesnt lag like a SOB?
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

ForeverZer0

Any money the bars are being refreshed with every update instead of only when they need changed.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Heretic86

Thats exactly what is happening.

The way it appears to be set up however is a little tricky to explain.  It looks like each bar is being drawn as a separate window (I think), and not as an object.  So update and refresh methods are never created.  It just redraws the graphics over and over again, well, when the Interpreter is running at least. 

For efficiency sake, would it be better to assign all the bars to one window, and update each time that one of the HP's of any of the characters has changed, or, would it be better to create a new window object for each actor to have their own separate HP bar window?
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

ForeverZer0

That makes no real difference, and the windows are objects, and there has to be some update of a sort, even if it is called from another class. I doubt that the Interpreter has anything to do with it either.

Somewhere in your scene, you need to find where the window or whatever is refreshed in a method that is/can be called every frame.
Check if the values are the same as the last update, and only actually refresh if they are not.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Heretic86

I'll show you what I got...

Spoiler: ShowHide
  #--------------------------------------------------------------------------
  # œ ƒŠƒtƒŒƒbƒVƒ...
  #--------------------------------------------------------------------------
  alias xrxs_bp7_refresh refresh
  def refresh
    if @update_cp_only
      # run the original refresh
    xrxs_bp7_refresh
    return
    end
    # •`ŽÊ,ð‹ÖŽ~,µ,È,ª,ç-ß,·
    @draw_ban = true

    xrxs_bp7_refresh
    # •`ŽÊ,̋֎~,ð‰ðœ
    @draw_ban = false
    # •`ŽÊ,ðŠJŽn
    @item_max = $game_party.actors.size
   
    for i in 0...$game_party.actors.size
    actor = $game_party.actors[i]
    actor_x = i * 160 + 21
    # Draw the Actor Graphic
      if not defined? actor_graphic or not defined? actor_id_drawn or actor.id != actor_id_drawn
        actor_id_drawn = actor.id
      actor_graphic = draw_actor_graphic(actor, actor_x - 9, 116) #if not interpreter_running
      end
     
    # HP/SP Bars
      draw_actor_hp_meter_line(actor, actor_x,  72, 96, 12)
    draw_actor_sp_meter_line(actor, actor_x, 104, 96, 12)
    # HP/SP Numbers
    self.contents.font.size = 24
      # Set Current HP Text Color
      self.contents.font.color = actor.hp == 0 ? knockout_color :
        actor.hp <= actor.maxhp / 4 ? critical_color :
        actor.hp <= actor.maxhp / 2 ? crisis_color : normal_color
    draw_shadow_text(actor_x-2, 58, 96, 24, actor.hp.to_s, 2) #if not interpreter_running
      # Set Current SP Text Color
      self.contents.font.color = actor.sp == 0 ? knockout_color :
        actor.sp <= actor.maxsp / 4 ? critical_color :
        actor.sp <= actor.maxsp / 2 ? crisis_color : normal_color
    draw_shadow_text(actor_x-2, 90, 96, 24, actor.sp.to_s, 2) #if not interpreter_running
    # --pŒêuHPv,Æ--pŒêuSPv,Ì•`ŽÊ
    self.contents.font.size = 12     # --pŒêuHP/SPv,Ì•¶Žš,Ì'å,«,³
    self.contents.font.color = system_color # --pŒêuHP/SPv,Ì•¶Žš,̐F
    draw_shadow_text(actor_x, 60, 96, 12, $data_system.words.hp) #if not interpreter_running
    draw_shadow_text(actor_x, 92, 96, 12, $data_system.words.sp) #if not interpreter_running
     
    draw_actor_state(actor, actor_x, 100) #if not interpreter_running
    end
  end

#============================================================================
# ¡ Window_Base
#============================================================================
class Window_Base < Window

  attr_accessor :draw_actor_hp_meter_line
  #--------------------------------------------------------------------------
  # Draws HP Meter Bar
  #--------------------------------------------------------------------------
  def draw_actor_hp_meter_line(actor, x, y, width = 156, height = 4)

    if not defined? @hp or actor.hp != @hp #or @actor_id != actor.id
      @actor_id = actor.id
      @hp = actor.hp

      w = width * actor.hp / actor.maxhp
      hp_color_1 = Color.new(255,   0,   0, 192)
      hp_color_2 = Color.new(255, 255,   0, 192)
      self.contents.fill_rect(x+8, y+4, width, (height/4).floor, Color.new(0, 0, 0, 128))
      draw_line(x, y, x + w, y, hp_color_1, (height/4).floor, hp_color_2)
      x -= 1
      y += (height/4).floor
      self.contents.fill_rect(x+8, y+4, width, (height/4).ceil , Color.new(0, 0, 0, 128))
      draw_line(x, y, x + w, y, hp_color_1, (height/4).ceil , hp_color_2)
      x -= 1
      y += (height/4).ceil
      self.contents.fill_rect(x+8, y+4, width, (height/4).ceil , Color.new(0, 0, 0, 128))
      draw_line(x, y, x + w, y, hp_color_1, (height/4).ceil , hp_color_2)
      x -= 1
      y += (height/4).ceil
      self.contents.fill_rect(x+8, y+4, width, (height/4).floor, Color.new(0, 0, 0, 128))
      draw_line(x, y, x + w, y, hp_color_1, (height/4).floor, hp_color_2)
    end
  end
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

Heretic86

Sorry for the Double Post, but if my text box extends to be more than one page, my focus jumps up to the top and I cant see what I am typing at the bottom.  External Javascript from some blocked site?

I see it is trying to do it in a refreshed method, and it doesnt look like an object is created to hold the hp bar, its just drawing it every time refresh comes up.

As far as the Interpreter involvement, it is also kind of strange to explain.  For example, I did a print "drew hp bar" when the hp bar is updated.  Updates 4 times.  It seems to call mostly correctly, when someone gets hit, it gets redrawn and updates, but if the Interpreter is running (I.E. battle event from Database -> Troops), it runs each and every frame while those page events are executing.  Not my script, Im trying to revise it to make it work...

I think I am back to having a more difficult time understanding how and what is happening, and I guess Im hoping for a bit of example script to work with so I can revise this accordingly...  Ton of work cuz it looks like I am going to have to do the same thing for the SP (Mana) Bars, the Progress bar, and all the "shadowed text" that the script already has in it...
Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)

ForeverZer0

The sole problem is not the refresh method, but what is calling it, and how often.
There is a bad error in there of every actor's bars being redrawn, when it should be only redrawn on a bar by bar basis when one requires change.

If you are looking for an example of one done correctly, check out what Blizz did in the gradient bars script inside Tons of Addons.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Heretic86

Current Scripts:
Heretic's Moving Platforms

Current Demos:
Collection of Art and 100% Compatible Scripts

(Script Demos are all still available in the Collection link above.  I lost some individual demos due to a server crash.)