Chaos Project

RPG Maker => RPG Maker Scripts => RMXP Script Database => Topic started by: ThallionDarkshine on December 13, 2012, 08:42:10 pm

Title: [XP] Ring Command Window
Post by: ThallionDarkshine on December 13, 2012, 08:42:10 pm
Ring Command Window
Authors: ThallionDarkshine
Version: 0.1
Type: Scripting Tool
Key Term: Scripting Tool



Introduction

This is just a script that aids in the creation of ring menus. It is a scripting tool that allows scripters to create ring command windows with icons and textual commands as well.


Features




Screenshots




Demo

None.


Script

Spoiler: ShowHide

class Window_RingCommand
  OPEN_DURATION = 40
  ROTATE_DURATION = 20
 
  attr_reader :index
 
  def initialize(commands, radius, x, y)
    @commands = commands.map { |i| i[0] }
    @icons = commands.map { |i| RPG::Cache.icon(i[1]) }
    @angle = 270
    @radius = 0
    @opacity = 0
    @dest_rad = radius
    @pos = [x, y]
    @spriteset = Spriteset_Ring.new(commands, radius, x, y)
    @opening = false
    @closing = false
    @rotating = false
    @index = 0
    self.open(OPEN_DURATION, 180, 64)
    update
  end
 
  def update
    if Input.repeat?(Input::LEFT) and !@opening and !@closing and !@rotating
      @index = (@index + 1) % @icons.length
      angle = (270 + 360 * (@icons.length - @index) / @icons.length) % 360
      duration = ROTATE_DURATION
      self.rotate(duration, angle, false)
    end
    if Input.repeat?(Input::RIGHT) and !@opening and !@closing and !@rotating
      @index = (@index + @icons.length - 1) % @icons.length
      angle = (270 + 360 * (@icons.length - @index) / @icons.length) % 360
      duration = ROTATE_DURATION
      self.rotate(duration, angle, true)
    end
    if @opening
      @frames += 1
      @radius = @dest_rad * @frames / @duration
      @angle = @s_angle + (270 - @s_angle) * @frames / @duration
      @opacity = 255 * 2 * @frames / @duration
      if @frames == @duration
        @opening = false
      end
    elsif @closing
      @frames += 1
      @radius = @s_rad * (@duration - @frames) / @duration
      @angle = @s_angle * @frames / @duration + @d_angle * (@duration - @frames) / @duration
      @opacity = 255 * (@duration - @frames) * 2 / @duration
      if @frames == @duration
        @closing = false
      end
    elsif @rotating
      @frames += 1
      @angle = @d_angle * @frames / @duration + @s_angle * (@duration - @frames) / @duration
      if @frames == @duration
        @rotating = false
      end
    end
    @spriteset.set(@radius, @angle, @pos, @opacity)
  end
 
  def open(duration, angle, radius)
    @s_angle = @angle = @angle - angle
    @dest_rad = radius
    @radius = 0
    @duration = duration
    @frames = 0
    @opening = true
  end
 
  def close(duration, angle)
    @s_angle = @angle
    @d_angle = @angle - angle
    @s_rad = @radius
    @duration = duration
    @frames = 0
    @closing = true
  end
 
  def rotate(duration, angle, right)
    @s_angle = @angle
    @d_angle = angle
    if right
      while @d_angle < @s_angle
        @d_angle += 360
      end
      while @d_angle - @s_angle > 360
        @d_angle -= 360
      end
    elsif !right
      while @d_angle > @s_angle
        @d_angle -= 360
      end
      while @s_angle - @d_angle > 360
        @d_angle += 360
      end
    end
    @duration = duration
    @frames = 0
    @rotating = true
  end
 
  def dispose
    @icons.each { |i| i.dispose }
    @spriteset.dispose
  end
end

class Spriteset_Ring
  def initialize(commands, radius, x, y)
    @commands = commands.map { |i| i[0] }
    @icons = commands.map { |i| RPG::Cache.icon(i[1]) }
    @icon_sprites = @icons.map { |icon| s=Sprite.new;s.bitmap=icon;s }
    @angle = 270
    @radius = radius
    @pos = [x, y]
    @tsprites = @commands.map { |i|
      s=Sprite.new
      s.bitmap=Bitmap.new(1,1)
      rect=s.bitmap.text_size(i)
      s.bitmap=Bitmap.new(rect.width,rect.height)
      s.bitmap.draw_text(rect,i,1)
      s.ox=rect.width/2
      s.oy=rect.height/2
      s.x,s.y=*@pos
      s
    }
  end
 
  def set(radius, angle, pos, opacity)
    @radius = radius
    @angle = angle
    @pos = pos
    @icon_sprites.each { |i| i.opacity = opacity }
    @tsprites.each { |s| s.x,s.y=*@pos }
    update
  end
 
  def update
    @icon_sprites.each_with_index { |icon, ind|
      angle = (@angle + 360 * ind / @icons.length) % 360
      d = 360 / @icons.length
      if angle > 270 - d and angle < 270 + d
        dist = (angle - 270).abs
        vals = [-120 * dist / d, 100 * dist / d]
        alpha = 255 * (d - dist) / d
        icon.tone = Tone.new(vals[0], vals[0], vals[0], vals[1])
        @tsprites[ind].opacity = alpha
      else
        icon.tone = Tone.new(-120, -120, -120, 100)
        @tsprites[ind].opacity = 0
      end
      angle *= Math::PI / 180
      x, y = Math.cos(angle) * @radius + @pos[0] - icon.bitmap.width / 2, Math.sin(angle) * @radius + @pos[1] - icon.bitmap.height / 2
      icon.x, icon.y = x, y
    }
  end
 
  def dispose
    @icon_sprites.each { |i| i.dispose }
    @icons.each { |i| i.dispose }
    @tsprites.each { |i| i.dispose }
  end
end



Instructions

To create a ring command window use this:
Window_RingCommand.new(commands, radius, x, y)

commands should be an array of arrays containing the icon name and the command name.


Compatibility

There shouldn't be any.


Credits and Thanks




Author's Notes

None