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.

Making An Icon Flash

Mac

Member

Basically what i want to do is make the item's icon flash when the cursor is on it, can anybody help me with this?

Thanks in advance!
 

Mac

Member

Umm well this is kinda hard to explain anymore, here goes:-

Say you have you skill menu and by default you use your cursor to select something, upon bringing the cursor over the selection the icon will begin to flash back and forth from white.

I hope that gives a better understanding.
 

Mac

Member

I know one way to do it would be to set a tone to the bitmap, add a count and then variate it as it goes along but i know theres an easier way, there always is :P
 
Use A Sprite + Window Sprites

Code:
=begin
============================================================================== 
 ** Window Sprites
------------------------------------------------------------------------------
Description:
------------
  This set allows for sprite objects to be tagged onto a window.
  
Method List:
------------
  Sprite
  ------
    tag
    in_rect?
  
Support Methods:
-------------
  Window_Base
  -----------
    initialize
    dispose
    update
    x=
    y=
    z=
    ox=
    oy=
    width=
    height=
    contents_opacity=
    back_opacity=
    opacity=
    visible=
    
  Sprite
  ------
    initialize
==============================================================================
=end
  
MACL::Loaded << 'Window Sprites'

class Window_Base
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  if @trick_sprites_windowbase.nil?
    alias_method :trick_sprites_base_x=, :x=
    alias_method :trick_sprites_base_y=, :y=
    alias_method :trick_sprites_base_z=, :z=
    alias_method :trick_sprites_base_ox=, :ox=
    alias_method :trick_sprites_base_oy=, :oy=
    alias_method :trick_sprites_base_width=, :width=
    alias_method :trick_sprites_base_height=, :height=
    alias_method :trick_sprites_base_contents_opacity=, :contents_opacity=
    alias_method :trick_sprites_base_back_opacity=, :back_opacity=
    alias_method :trick_sprites_base_opacity=, :opacity=
    alias_method :trick_sprites_base_visible=, :visible=
    @trick_sprites_windowbase = true
  end
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  alias_method :trick_sprites_base_initialize, :initialize
  def initialize(x, y, width, height)
    # Setup Sprites Array
    @window_sprites = []
    # The Usual
    trick_sprites_base_initialize(x, y, width, height)
  end
  #--------------------------------------------------------------------------
  # * Dispose
  #--------------------------------------------------------------------------
  alias_method :trick_sprites_base_dispose, :dispose
  def dispose
    # The Usual
    trick_sprites_base_dispose
    # Dispose all Sprites
    @window_sprites.each {|sprite| sprite.dispose}
  end
  #--------------------------------------------------------------------------
  # * Update
  #--------------------------------------------------------------------------
  alias_method :trick_sprites_base_update, :update
  def update
    # The Usual
    trick_sprites_base_update
    # Update
    @window_sprites.each {|sprite| sprite.update}
  end
  #--------------------------------------------------------------------------
  # * Set X
  #--------------------------------------------------------------------------  
  def x=(x)
    # Run through each window sprite
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch by Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          # Include Scroll Calculation Set X
          sprite.x = sprite.x - self.x + x + ox
        when 'border'
          # Exclude Scroll Calculation Set X
          sprite.x = sprite.x - self.x + x
        end
      else
        # Default is Content Sprite
        sprite.x = sprite.x - self.x + x + ox
      end
    end
    # The Usual
    self.trick_sprites_base_x = x
  end
  #--------------------------------------------------------------------------
  # * Set Y
  #-------------------------------------------------------------------------- 
  def y=(y)
    # Update All Y's
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch by Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          # Include Scroll Calculation Set Y
          sprite.y = sprite.y - self.y + y + oy
        when 'border'
          # Exclude Scroll Calculation Set Y
          sprite.y = sprite.y - self.y + y
        end
      else
        # Default is Content Sprite
        sprite.y = sprite.y - self.y + y + oy
      end
    end
    # The Usual
    self.trick_sprites_base_y = y
  end
  #--------------------------------------------------------------------------
  # * Set Z
  #-------------------------------------------------------------------------- 
  def z=(z)
    # Update All Z's
    @window_sprites.each do |sprite| 
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch By Sprite Type
        case sprite.sprite_type
        when 'content'
          sprite.z = self.z + 1
        when 'content2'
          sprite.z = self.z + 2
        when 'cover', 'border'
          sprite.z = self.z + 3
        when 'background'
          sprite.z = self.z
        end
      else
        # Default is content
        sprite.z = self.z + 1
      end
    end
    # The Usual
    self.trick_sprites_base_z = z
  end
  #--------------------------------------------------------------------------
  # * Set Origin X
  #-------------------------------------------------------------------------- 
  def ox=(ox)
    # Get Ox Change
    cx = self.ox - ox
    # Run Through Each Sprite
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch By Sprite Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          # Add to X
          sprite.x += cx
          # Setup Visibility
          sprite.visible = sprite.x.between?(x + 16, x + width - 16) && visible
        end
      else
        # Add to X
        sprite.x += cx
        # Setup Visibility
        sprite.visible = sprite.x.between?(x + 16, x + width - 16) && visible
      end
    end
    # The Usual
    self.trick_sprites_base_ox = ox
  end
  #--------------------------------------------------------------------------
  # * Set Origin Y
  #-------------------------------------------------------------------------- 
  def oy=(oy)
    # Get Oy Change
    cy = self.oy - oy
    # Run Through Each Sprite
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch By Sprite Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          # Add to Y
          sprite.y += cy
          # Setup Visibility
          sprite.visible = sprite.y.between?(y + 16, y + height - 16) && visible
        end
      else
        # Add to Y
        sprite.y += cy
        # Setup Visibility
        sprite.visible = sprite.y.between?(y + 16, y + height - 16) && visible
      end
    end
    # The Usual
    self.trick_sprites_base_oy = oy
  end
  #--------------------------------------------------------------------------
  # * Set Width
  #-------------------------------------------------------------------------- 
  def width=(width)
    # Run Through Each Sprite
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch By Sprite Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          # Setup Visibility
          sprite.visible = sprite.x.between?(x + 16, x + width - 16) && visible
        end
      else
        # Setup Visibility
        sprite.visible = sprite.x.between?(x + 16, x + width - 16) && visible
      end
    end
    # The Usual
    self.trick_sprites_base_width = width
  end
  #--------------------------------------------------------------------------
  # * Set Height
  #-------------------------------------------------------------------------- 
  def height=(height)
    # Run Through Each Sprite
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch By Sprite Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          # Setup Visibility
          sprite.visible = sprite.y.between?(y + 16, y + height - 16) && visible
        end
      else
        # Setup Visibility
        sprite.visible = sprite.y.between?(y + 16, y + height - 16) && visible
      end
    end
    # The Usual
    self.trick_sprites_base_height = height
  end
  #--------------------------------------------------------------------------
  # * Set Contents Opacity
  #-------------------------------------------------------------------------- 
  def contents_opacity=(opacity)
    # Run Through Each Sprite and Setup Opacity
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch By Sprite Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          # Setup Opacity
          sprite.opacity = opacity
        end
      else
        # Setup Opacity
        sprite.opacity = opacity
      end
    end
    # The Usual
    self.trick_sprites_base_contents_opacity = opacity
  end
  #--------------------------------------------------------------------------
  # * Set Back Opacity
  #-------------------------------------------------------------------------- 
  def back_opacity=(opacity)
    # Run Through Each Sprite and Setup Opacity
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch By Sprite Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          # Setup Opacity
          sprite.opacity = opacity
        end
      else
        # Setup Opacity
        sprite.opacity = opacity
      end
    end
    # The Usual
    self.trick_sprites_base_back_opacity = opacity
  end
  #--------------------------------------------------------------------------
  # * Set Opacity
  #-------------------------------------------------------------------------- 
  def opacity=(opacity)
    # Run Through Each Sprite and Setup Opacity
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch By Sprite Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          # Setup Opacity
          sprite.opacity = opacity
        end
      else
        # Setup Opacity
        sprite.opacity = opacity
      end
    end
    # The Usual
    self.trick_sprites_base_opacity = opacity
  end
  #--------------------------------------------------------------------------
  # * Set Visibility
  #-------------------------------------------------------------------------- 
  def visible=(bool)
    # Get Rect
    rect = Rect.new(x + 16, y + 16, width - 32, height - 32)
    # Run Through Each Sprite
    @window_sprites.each do |sprite|
      # If Has Method sprite type
      if sprite.respond_to?(:sprite_type)
        # Branch By Sprite Type
        case sprite.sprite_type
        when 'content', 'content2', 'cover', 'background'
          sprite.visible = bool && sprite.in_rect?(rect)
        when 'border', 'tagged'
          sprite.visible = visible
        end
      else
        sprite.visible = bool && sprite.in_rect?(rect)
      end
    end
    # Update Visibility
    self.trick_sprites_base_visible = bool
  end
end

class Sprite
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :sprite_type
  #--------------------------------------------------------------------------
  # * Alias Listings
  #--------------------------------------------------------------------------
  if @trick_sprites_sprite.nil?
    alias_method :trick_sprites_sprite_initialize, :initialize
    @trick_sprites_sprite = true
  end
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize(*args)
    # The Usual
    trick_sprites_sprite_initialize(*args)
    # Setup Default for sprite_type - 'content'
    @sprite_type = 'content'
  end
  #-------------------------------------------------------------------------
  # * Name      : Tag
  #   Info      : Tags a sprite to a window
  #   Author    : Trickster
  #   Call Info : Window window - window to tag sprite to
  #-------------------------------------------------------------------------
  def tag(window)
    # Get Attributes
    x, y, width, height = window.x, window.y, window.width, window.height
    # Setup Rect
    rect = Rect.new(x + 16, y + 16, width - 32, height - 32)
    # Branch by Sprite Type
    case sprite_type
    when 'content'
      # Set Visibility
      self.visible = in_rect?(rect) && window.visible
      # Set Z Between Window
      self.z = window.z + 1
      # Setup Opacity
      self.opacity = window.contents_opacity
    when 'content2'
      # Set Visibility
      self.visible = in_rect?(rect) && window.visible
      # Set Z Between Window
      self.z = window.z + 2
      # Setup Opacity
      self.opacity = window.contents_opacity
    when 'cover'
      # Set Visibility
      self.visible = in_rect?(rect) && window.visible
      # Set Z Between Window
      self.z = window.z + 3
      # Setup Opacity
      self.opacity = window.contents_opacity
    when 'border'
      # Set Visibility
      self.visible = window.visible
      # Set Z Between Window
      self.z = window.z + 3
      # Setup Opacity
      self.opacity = window.opacity
    when 'background'
      # Set Visibility
      self.visible = in_rect?(rect) && window.visible
      # Set Z at Window
      self.z = window.z
      # Setup Opacity
      self.opacity = window.back_opacity
    when 'tagged'
      # Set Visibility
      self.visible = window.visible
      # Setup Opacity
      self.opacity = window.opacity
    end
  end
  #-------------------------------------------------------------------------
  # * Name      : In Rectangle?
  #   Info      : Is Sprite in Rectangle
  #   Author    : Trickster
  #   Call Info : One or Four Arguments
  #                 Rect rect - rectangle to check
  #                 Integer x, y, width, height - rectangle to check
  #-------------------------------------------------------------------------
  def in_rect?(*rect)
    # If 1 Argument Sent
    if rect.size == 1
      # Get Rect
      rect = rect[0]
      # Return in rect state
      return (x.between?(rect.x, rect.x + rect.width) && 
      y.between?(rect.y, rect.y + rect.height))
    else
      # Get variables sent
      x, y, width, height = rect
      # If In Rect
      return self.x.between?(x, x + width) && self.y.between?(y, y + height)
    end
  end
end

you may remove this line
Code:
MACL::Loaded << 'Window Sprites'

Well when drawing the icon instead draw a sprite (an RPG::Sprite) with the icon as the bitmap, push the sprite to the @window_sprites array of the window class

In the index= method set the sprite that the cursor is on to blink (by using RPG::Sprites blink_on method) and set the old index's sprite to stop blinking (by using the blink_off method)

well there is one way of doing it another would be to constantly erase and redraw the bitmap every frame to get a flash effect.
 
And if it helps, this is my animated icons sprite, used in my item/skill menu. It works nicely with script Trickster just posted. you can use it as a base.
Code:
#==========================================================================
class Sprite_Icon < Sprite
  #--------------------------------------------------------------------------
  def initialize(x, y, icon_name, window = nil, opacity = 255)
    if window.is_a?(Window)
      super(window.viewport)
      self.x = window.x + 16 - window.ox + x
      self.y = window.y + 16 - window.oy + y
      self.tag(window)
    else
      super()
      self.x, self.y = x, y
    end
    icon = RPG::Cache.icon(icon_name)
    self.bitmap = Bitmap.new(icon.width, icon.height)
    self.bitmap.blt(0, 0, icon, Rect.new(0, 0, icon.width, icon.height), opacity)
    cols, rows = icon.width / 24, icon.height / 24
    @rects = []
    for i in 0...rows
      for j in 0...cols
        @rects << Rect.new(j * 24, i * 24, 24, 24)
      end
    end
    @frame_count = 0
    @anim_frames = 8
    self.src_rect.set(0, 0, 24, 24)
  end
  #--------------------------------------------------------------------------
  def update
    super
    @frame_count = (@frame_count + 1) % (@anim_frames * @rects.size)
    index = @frame_count / @anim_frames
    rect = @rects[index]
    self.src_rect.set(rect.x, rect.y, 24, 24)
  end
  #--------------------------------------------------------------------------
end
#==========================================================================
Maybe you have to replace my update method for your effect, and allowing the window to disable the animation if not selected.
 

Mac

Member

Thanks trick and tibuda, still encountering some incorperation problems though, heres the script, i'd be gratefull if you could mod it so.

Code:
#==============================================================================
# ** Window_Skill
#------------------------------------------------------------------------------
#  This window displays usable skills on the skill and battle screens.
#==============================================================================

class Window_IconSkill < Window_Selectable
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     actor : actor
  #--------------------------------------------------------------------------
  def initialize(actor)
    super(0, 120, 640, 352)
    @actor = actor
    @column_max = 20
    refresh
    self.index = 0
    # If in battle, move window to center of screen
    # and make it semi-transparent
    if $game_temp.in_battle
      self.y = 303
      self.x = -12
      self.height = 66
      self.back_opacity = 0
      self.opacity = 0
    end
  end
  #--------------------------------------------------------------------------
  # * Acquiring Skill
  #--------------------------------------------------------------------------
  def skill
    return @data[self.index]
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    if self.contents != nil
      self.contents.dispose
      self.contents = nil
    end
    @data = []
    for i in 0...@actor.skills.size
      skill = $data_skills[@actor.skills[i]]
      if skill != nil
        @data.push(skill)
      end
    end
    # If item count is not 0, make a bit map and draw all items
    @item_max = @data.size
    if @item_max > 0
      self.contents = Bitmap.new(width - 32, row_max * 32)
      for i in 0...@item_max
        draw_item(i)
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Draw Item
  #     index : item number
  #--------------------------------------------------------------------------
  def draw_item(index)
    skill = @data[index]
    if @actor.skill_can_use?(skill.id)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    x = 4 + index *  32
    y = 0
    rect = Rect.new( x, y, self.width / @column_max - 32, 32)
    self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))
    bitmap = RPG::Cache.icon(skill.icon_name)
    opacity = self.contents.font.color == normal_color ? 255 : 128
    self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)
  end
  #--------------------------------------------------------------------------
  # * Help Text Update
  #--------------------------------------------------------------------------
  def update_help
    @help_window.set_text(self.skill == nil ? "" : self.skill.description)
    @help_window.y = 25
  end
end
 
Trickster's Window_Sprite script is perfect for that.
You will need to modify your Window_IconSkill because it's using bitmap.blt. I guess you can remove a few lines in the draw_item methode of WindowIconSkill.
Code:
def draw_item(index)
    skill = @data[index]
    if @actor.skill_can_use?(skill.id)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    x = 4 + index % 2 * (288 + 32)
    y = index / 2 * 32
    [COLOR=red]rect = Rect.new(x, y, self.width / @column_max - 32, 32)[/COLOR]
[COLOR=red]   self.contents.fill_rect(rect, Color.new(0, 0, 0, 0))[/COLOR]
[COLOR=red]   bitmap = RPG::Cache.icon(skill.icon_name)[/COLOR]
[COLOR=red]   opacity = self.contents.font.color == normal_color ? 255 : 128[/COLOR]
[COLOR=red]   self.contents.blt(x, y + 4, bitmap, Rect.new(0, 0, 24, 24), opacity)[/COLOR]
    self.contents.draw_text(x + 28, y, 204, 32, skill.name, 0)
    self.contents.draw_text(x + 232, y, 48, 32, skill.sp_cost.to_s, 2)
  end
The lines in red are useless if you are using Trickster's methode.
In your scene add something like:
Code:
icon = Sprite.new
icon.bitmap =  bitmap 
icon.tag(@iconskill_window)

Correct me if i am wrong but you will need to draw each icon sprites within the scene instead of the window. I tried last night and it works fine.
 

Mac

Member

That still doesn't work Dargor, you need something in a window to say that there is an icon there and since removing those lines nothing will appear, whatever needs to be done needs to be done in the Window Class.

Thanks for trying.
 
It's not this way;
Code:
def draw_item(index)
    skill = @data[index]
    if @actor.skill_can_use?(skill.id)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    x = 4 + index % 2 * (288 + 32)
    y = index / 2 * 32
[COLOR=Red]    if @icon_sprites[skill.id].nil?
      sprite = Sprite_FlashIcon.new(skill.icon_name)
      sprite.bitmap =  bitmap
      sprite.x = self.x + 16 - self.ox + x
      sprite.y = self.y + 16 - self.oy + y + 4
      sprite.tag(self)
      @window_sprites << sprite
      @icon_sprites[skill_id] = sprite
    end[/COLOR]
    self.contents.draw_text(x + 28, y, 204, 32, skill.name, 0)
    self.contents.draw_text(x + 232, y, 48, 32, skill.sp_cost.to_s, 2)
  end
Adding the following to your initialize method, before calling refresh:
Code:
@icon_sprites = {}
And adding the following at the end of your refresh method
Code:
    if @item_max > 0
      self.contents = Bitmap.new(width - 32, row_max * 32)
[COLOR=Red]      @icon_sprites.each do |id, sprite|
        sprite.dispose
        @window_sprites.delete(sprite)
      end[/COLOR]
      for i in 0...@item_max
        draw_item(i)
      end
    end
  end
And we still have to make some coding for the Sprite_FlashIcon class.
 
I added @icons = [] in the initialize methode and each time draw_item is called, I add a new sprite in it (placed the exact same way you did tubuda). I also added a methode.
Code:
def flash_icon(index)
  if self.index == index
    @icons[index].blink_on
    @icons[index].update
  else
    for icon in @icons
      icon.blink_off
    end
  end
end
I don't use any new sprite class but it could be useful for more flexibility.
In my skill scene, in update, I put @skill_window.flash_icon(@skill_window.index)

It worked well for me.
 
And now its my turn

Code:
  def draw_item(index)
    skill = @data[index]
    if @actor.skill_can_use?(skill.id)
      self.contents.font.color = normal_color
    else
      self.contents.font.color = disabled_color
    end
    x = 4 + index % 2 * (288 + 32)
    y = index / 2 * 32
    if @icon_sprites[index].nil?
      sprite = RPG::Sprite.new(skill.icon_name)
      sprite.bitmap =  RPG::Cache.icon(skill.icon_name)
      sprite.x = self.x + 16 - self.ox + x
      sprite.y = self.y + 16 - self.oy + y + 4
      sprite.tag(self)
      @window_sprites << sprite
      @icon_sprites[index] = sprite
    end
    self.contents.draw_text(x + 28, y, 204, 32, skill.name, 0)
    self.contents.draw_text(x + 232, y, 48, 32, skill.sp_cost.to_s, 2)
  end

Now to get the sprite to flash

Code:
alias_method :trick_flashicon_index=, :index=
def index=(index)
  # Turn Flash for old index off
  @icon_sprites[self.index].blink_off
  # The Usual
  trick_flashicon_index = index
  # Turn Flash for new index on
  @icon_sprites[self.index].blink_on
end

Untested but it should work

You also have to add @icon_sprites = {} in the initialize method

note: I didn't account for if the data was changed I will edit to account for that after I get back from my Computer Science Final Go Me!!!
 

Mac

Member

Thanks guys.

I tried all techs but tricksters seems to be the closest to accomplishing the job, but i get this error on line 375 of your code, take in mind that i removed the MACL part you told me to move, so it used to be line 376. And it says it can't turn the string into a viewport.
 
oops hehe I used tibuda's code as a base (since it was close to what I was thinking of doing) and forgot to remove the skill.icon_name from RPG::Sprite.new(skill.icon_name)

but yeah credit goes to tibuda for that code, I just edited it :)
 

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