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.

[XP]Ring Menu Speed

Hi I'm developing a command window to battle with the aid of the Ring Menu created by Trebor777, but I face a little problem.

I wonder what part of the script is set the speed with which the Ring Menu moves.

The script is below:

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

=begin

RING MENU advanced.

by Trebor777

v1.8.1

24/07/2009

An independant, class free, Ring menu, easily usable, with a lot of options.

=end

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

class Array

  # rotate  n item(s) to the left ( first becomes last) as a new array

  def rotate_l(n=1)

    a = self.clone

    n.times{a.push(a.shift)}

    return a

  end

  # rotate  n item(s) to the right ( last becomes first) as a new array

  def rotate_r(n=1)

    a = self.clone

    n.times{a.unshift(a.pop)}

    return a

  end

  # rotate n item(s) to the left

  def rotate_l!(n=1)

    n.times{self.push(self.shift)}

    return self

  end

  # rotate n item(s) to the right

  def rotate_r!(n=1)

    n.times{self.unshift(self.pop)}

    return self

  end

  # Do the sum of all the items. (they need to be all of the same type)

  def sum

    inject( nil ) { |sum,x| sum ? sum+x : x if x.respond_to? "+" }

  end

end

module Sound

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

  # * Play Sound Effect

  #     se : sound effect to be played

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

  def self.se_play(se)

    if se != nil and se.name != ""

      Audio.se_play("Audio/SE/" + se.name, se.volume, se.pitch)

    end

  end

  

  def self.play_cursor

    se_play($data_system.decision_se) unless $data_system.nil?

  end

end

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

class Ring_Menu

  RESO = 4

  PLAY_SE = true

  SELECTED_ANGLE= Math::PI/2.0 # 90°CW to set the "0" at the bottom

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

  attr_reader :options, :h_radius, :v_radius, :center, :zoom, :visible, :opacity, :zoom_max, :reso

  attr_accessor :active, :index

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

  def initialize(h_rad=10,v_rad=10,center=Table.new(2),options=[])

    @options=options

    @v_radius=v_rad

    @h_radius=h_rad

    @center = center

    @index=0

    @reso = RESO

    @visible = true

    @zoom_max = 1.4

    @opacity = 255

    @active = true

    @zoom = true

    @angle = h_rad == 0 ? 0 : SELECTED_ANGLE

    process

  end

  # Attributes

  def options=(a=[])

    @options=a

    @index=0

    process

  end

 

  def vertical?

    @h_radius == 0

  end

 

  def x

    @center[0]

  end

  def y

    @center[1]

  end

  def x=(*args)

    @center[0]= args.first

    process

  end

  def y=(*args)

    @center[1]= args.first

    process

  end

  def visible=(value)

    @visible = value

    @options.each{|opt| opt.sprite.visible=value if !opt.nil?}

  end

  def opacity=(value)

    value = 0 if value < 0

    value = 255 if value > 255

    @opacity = value

    @options.each{|opt| opt.sprite.opacity=value}

  end

  def h_radius=(value)

    @h_radius = value

  end

  def v_radius=(value)

    @v_radius = value

  end

  def center=(value)

    @center = value

  end

  def zoom=(value)

    @zoom = value

    draw

  end

 

  def reso=(v)

    @reso = v

    process

  end

 

  def zoom_max=(value)

    @zoom_max= value

    process

  end

  # ENd Attributes

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

  # Update

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

  def update

    return if !self.active or !self.visible

    update_flag = (@old_center!=@center or @old_hr != @h_radius or @old_vr != @v_radius)

    if Input.repeat?(vertical? ? Input::UP : Input::LEFT)

      loop do

        rotate

        break unless self.selected.disabled

      end

    elsif Input.repeat?(vertical? ? Input::DOWN : Input::RIGHT)

      loop do

        rotate(1)

        break unless self.selected.disabled

      end

    end

    process if update_flag

  end

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

# Process: Create/recreate according to the menu attributes, the position/zoom values of the options, and store them into arrays.

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

  def process

    # return if the menu is empty.

    return if @options.empty?

    # Get the maximum size for the arrays.

    max_data=@options.size*@reso

    # Divide a circle(2*Pi) by the numbers of options.

    @base_angle = Math::PI*2.0/max_data

    @zoom_step = (@zoom_max-0.5)/(max_data/2.0)

    # set an array having precalculated pair of coordinates so we don't have to

    # get process them for each rotation(we simply switch the options coords)

    @coord_set= Array.new(max_data,0)

    # and for zoom values as well

    @zoom_set = Array.new(max_data,0)

    max_data.times do |i|

      angle = i*@base_angle+@angle

      x = (Math::cos(angle)*@h_radius)+@center[0]

      y = (Math::sin(angle)*@v_radius)+@center[1]

      @coord_set[i]=([x,y])

      @zoom_set[i]= i<max_data/2.0 ? @zoom_max-@zoom_step*i : @zoom_set[max_data/2.0-i-max_data/2.0-1]

    end

 

    val = (@index % max_data)+1+((@reso-4)/2.0).round

   

    @coord_set.rotate_r!(val)

    @zoom_set.rotate_r!(val)

    @old_center = @center

    @old_hr = @h_radius

    @old_vr = @v_radius

    draw

    self.selected.selected = true

    if @h_radius==0

      self.selected.sprite.z =1000

    end

  end

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

  # Draw the options according to the current index

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

  def draw

    @coord_set.each_index do |index|

      i = (index / @reso.to_f).round

      # next iteration if the current option is not a RMenu_Option

      next if !@options[i].is_a?(RMenu_Option)

      # Set the Option coords

      (@options[i]).coord = @coord_set[index]

      # Set the option's Z-index to its y.

      @options[i].z = @coord_set[index][1]

      #@options.zoom = 1.0 if !@zoom

      @options[i].zoom = @zoom? @zoom_set[index] : 1.0

      #@options[i].selected = (@options[i]==self.selected)

    end

    @old_zoom = @zoom

    Graphics.update

  end

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

  # Rotate the menu options

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

  def rotate(way=0)# 0 = left, 1 = right

    self.selected.selected = false

    Sound.play_cursor if PLAY_SE

    frcount = Graphics.frame_count # Save the current frame count ( -> Game Time )

      @index += way*2-1

      @index %= @options.size

      @reso.times do

        if way==0

          @coord_set.rotate_l!

          @zoom_set.rotate_l!

        elsif way==1

          @coord_set.rotate_r!

          @zoom_set.rotate_r!

        end

        draw

      end

    self.selected.selected = true

    if @h_radius==0

      self.selected.sprite.z =1000 # Set the selected option to the top

    end

    Graphics.frame_count = frcount # Reset the frame count to the previous value

  end

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

  # Return the current selected option

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

  def selected

    @options[@index % @options.size]

  end

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

  # Dispose the menu (and all the options)

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

  def dispose

    @options.each{|opt| opt.dispose}

  end

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

  # * Save State

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

  def save_state

    @state_visible = self.visible

    @state_active = self.active

  end

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

  # * Load State

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

  def load_state

    self.visible = @state_visible unless @state_visible.nil?

    self.active = @state_active unless @state_active.nil?

  end

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

  # * Hide

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

  def hide

    self.visible = false

    self.active = false

  end

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

  # * Show

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

  def show

    self.visible = true

    self.active = true

  end

end

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

# Menu option class

class RMenu_Option

  attr_reader :name, :icon, :coord, :sprite, :selected, :disabled

  attr_accessor :angle

  def initialize(name="",icon=0,viewport=nil,&block)

    @name=name

    @icon=icon

    @block=block

    @angle = 0

    @coord=Table.new(2)

    @disabled = false

    @sprite = Sprite.new(viewport)

    @sprite.bitmap = RPG::Cache.icon(name)

    #p @sprite.bitmap.width/2,@sprite.bitmap.height/2

    @sprite.ox = @sprite.bitmap.width/2

    @sprite.oy = @sprite.bitmap.height/2

    @selected = false

    @sprite.tone.gray = 255

  end

  def call

    return if @block.nil?

    @block.call

  end

  def z=(value)

    @sprite.z = value

  end

  def selected=(v)

    if v != @selected

      @sprite.tone.gray = (v==true ? 0 : 255)

      @selected = v==true

    end

  end

  def disabled=(v)

    @disabled= v==true

  end

  def coord=(c = [0,0])

    @coord=c

    @sprite.x = @coord[0]

    @sprite.y = @coord[1]

  end

  def x=(*args)

    @coord[0]= args.first

    @sprite.x= args.first

  end

  def y=(*args)

    @coord[1]= args.first

    @sprite.y= args.first

  end

  def zoom=value

    @sprite.zoom_x = value

    @sprite.zoom_y = value

  end

  def dispose

    @coord=nil

    @block=nil

    @sprite.dispose

  end

end

I thank the attention.

Kiryo!
 
:) Yeah I should have commented the Variable for that.
It's the resolution variable, i called it resolution rather than speed because, it's more about how smooth the rotation will be rather than speed... obviously if it's not smooth at all, it's the fastest, but you won't see movement, or should i say the intermediary positions.
You can either, reduce the RESO constant, so that every ring menu created are affected, or you can change the resolution independantly for each menu, after creation :

@r_menu.reso = 2
as an example.

Hope it helps

EDIT I'll probably go through a minor update for XP and VX, to clean the code and alter slightly the way it works: currently, because i wanted it as plug&play as possible, the menu updates itself by hanging the rest of the game using "graphics.update" in its own loop, which basically stop updating whatever was moving before changing the menu.
I've fixed that for the GOSU+Chingu version of the menu, but not for XP and VX. :)

I'll make things a bit easier to read as well to help understanding what's going on. I'll do that on wednesday :).
 

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