Implementing the Invalidate Pattern for sprites

Thu, 09 Aug 2007 22:43:11 -0400 - Author:

In RGSS, when drawing and displaying sprites that dynamically change, it is helpful to implement the Invalidate pattern, which marks a sprite as invalid whenever something causes it to force a redraw. This technique was inspired by the refresh method in the Window_Base and Window_Selectable classes and its derived classes.

The difference, however, is that refresh can, under certain circumstances, be called many times between frames, which can cause the window to be redrawn more often than necessary. With the invalidate pattern, the sprite or window is redrawn only when necessary, and only once during a frame. The invalidate pattern uses a "repaint" method to do so.

Here I present a class called InvalidatableSprite which is derived from Sprite and illustrates the pattern.

class InvalidatableSprite < Sprite
 def initialize(viewport)
  super
  @invalid=false
 end
 # Marks that the control must be redrawn to reflect current logic.
 def invalidate
  @invalid=true
 end
 # Determines whether the control is invalid
 def invalid?
  return @invalid
 end
 # Marks that the control is valid.  Normally called only by repaint.
 def validate
  @invalid=false
 end
 # Redraws the sprite only if it is invalid, and then
 # revalidates the sprite
 def repaint
  if self.invalid?
   refresh
   validate
  end
 end
 # Redraws the sprite.  This method should not check whether
 # the sprite is invalid, to allow it to be explicitly called.
 def refresh
 end
 # Updates the logic on the sprite, for example, in response
 # to user input, and invalidates it if necessary.  This should
 # be called only once per frame.
 def update
  super
 end
end

The way it works is that invalidate is called just after some logic that causes the sprite's logic to change, and that repaint is called during the update loop (where Graphics.update is).