This is a class for
scripters who for whatever reason want to have a command window display in a ring, obviously you could make a ring menu system, but with some creative thinking you could for example make a safe opening minigame without too much difficulty.
Anyway here's the script:
class Window_Ring_Command < Window_Base
attr_accessor :index
Turn_Frames = 20
def initialize(x_pos, y_pos, commands, radius = 150.0)
super(0, 0, 640, 480)
@x_pos = x_pos
@y_pos = y_pos
@commands = commands
@index = 0
@moving = 0
@radius = radius
@radius = radius
self.contents = Bitmap.new(width-32, height-32)
self.opacity = 0
refresh
end
def update
super
if @moving != 0
refresh
end
end
def refresh
self.contents.clear
if @moving != 0
@moving = (Math.abs(@moving) - 1) * (@moving/Math.abs(@moving))
end
max_item = @commands.size
pi_part = (2 * Math::PI) / max_item
for i in 0...max_item
x = (@radius * Math.sin((i * pi_part) + (@moving * (pi_part/Turn_Frames)))) + @x_pos
x = x.to_i
y = (@radius * Math.cos((i * pi_part) + (@moving * (pi_part/Turn_Frames)))) + @y_pos
y = y.to_i
draw_item(x, y, i)
end
end
def draw_item(x, y, i)
k = i + @index
if k >= @commands.size
k -= @commands.size
end
self.contents.draw_text(x, y, 150, 32, @commands[k])
end
def move_right
@index += 1
if @index >= @commands.size
@index -= @commands.size
end
@moving += Turn_Frames
end
def move_left
@index -= 1
if @index < 0
@index += @commands.size
end
@moving -= Turn_Frames
end
def moving?
return @moving != 0
end
end
module Math
def self.abs(x)
if x >= 0
return x
else
return -1 * x
end
end
end
To use the constant Turn_Frames is how many frames or whatever you want to call them it takes to rotate to the next option in the command window.
The paranthesis when initialising are:
x_pos - The x co-ordinate of the ring/circle (CENTRE)
y_pos - The y co-ordinate of the ring/circle (CENTRE)
commands - The commands you want in the rung
radius = 150.0 - Basically you don't have to bother with this unless you want a smaller or larger ring/circle.
The methods you need to know:
update - call it as you would a normal command window
moving? - use this if you want to check if the menu is rotating (ie to stop them pushing left again)
move_left - moves the menu left (equivelent of up on a normal command window)
move_right - moves the menu left (equivelent of down on a normal command window).
I hope this is of use to someone, I'm willing to help and maybe make a few examples of how to use this if needed, but I'm busy with college work at the moment so don't expect speedy responces.
Add-Ons
Choices in a ring menu.
Script:
class Game_Temp
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :choices
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
alias choices_initialize initialize
def initialize
choices_initialize
@choices = []
end
end
class Interpreter
#--------------------------------------------------------------------------
# * Setup Choices
#--------------------------------------------------------------------------
def setup_choices(parameters)
# Set choice item count to choice_max
$game_temp.choice_max = parameters[0].size
# Set choice to message_text
$game_temp.choices = []
for text in parameters[0]
$game_temp.choices.push(text)
end
# Set cancel processing
$game_temp.choice_cancel_type = parameters[1]
# Set callback
current_indent = @list[@index].indent
$game_temp.choice_proc = Proc.new { |n| @branch[current_indent] = n }
end
end
class Window_Message < Window_Selectable
#--------------------------------------------------------------------------
# * Terminate Message
#--------------------------------------------------------------------------
alias choices_terminate terminate_message
def terminate_message
choices_terminate
if @choice_window != nil
@choice_window.dispose
@choice_window = nil
end
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
self.contents.font.color = normal_color
x = y = 0
@cursor_width = 0
# Indent if choice
if $game_temp.choice_start == 0
x = 8
end
# If waiting for a message to be displayed
if $game_temp.message_text != nil
text = $game_temp.message_text
# Control text processing
begin
last_text = text.clone
text.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
end until text == last_text
text.gsub!(/\\[Nn]\[([0-9]+)\]/) do
$game_actors[$1.to_i] != nil ? $game_actors[$1.to_i].name : ""
end
# Change "\\\\" to "\000" for convenience
text.gsub!(/\\\\/) { "\000" }
# Change "\\C" to "\001" and "\\G" to "\002"
text.gsub!(/\\[Cc]\[([0-9]+)\]/) { "\001[#{$1}]" }
text.gsub!(/\\[Gg]/) { "\002" }
# Get 1 text character in c (loop until unable to get text)
while ((c = text.slice!(/./m)) != nil)
# If \\
if c == "\000"
# Return to original text
c = "\\"
end
# If \C[n]
if c == "\001"
# Change text color
text.sub!(/\[([0-9]+)\]/, "")
color = $1.to_i
if color >= 0 and color <= 7
self.contents.font.color = text_color(color)
end
# go to next text
next
end
# If \G
if c == "\002"
# Make gold window
if @gold_window == nil
@gold_window = Window_Gold.new
@gold_window.x = 560 - @gold_window.width
if $game_temp.in_battle
@gold_window.y = 192
else
@gold_window.y = self.y >= 128 ? 32 : 384
end
@gold_window.opacity = self.opacity
@gold_window.back_opacity = self.back_opacity
end
# go to next text
next
end
# If new line text
if c == "\n"
# Update cursor width if choice
if y >= $game_temp.choice_start
@cursor_width = [@cursor_width, x].max
end
# Add 1 to y
y += 1
x = 0
# Indent if choice
if y >= $game_temp.choice_start
x = 8
end
# go to next text
next
end
# Draw text
self.contents.draw_text(4 + x, 32 * y, 40, 32, c)
# Add x to drawn text width
x += self.contents.text_size(c).width
end
end
# If choice
if $game_temp.choice_max > 0
# EDIT
@choice_window = Window_Ring_Command.new(280, 180, $game_temp.choices,60)
# /EDIT
end
# If number input
if $game_temp.num_input_variable_id > 0
digits_max = $game_temp.num_input_digits_max
number = $game_variables[$game_temp.num_input_variable_id]
@input_number_window = Window_InputNumber.new(digits_max)
@input_number_window.number = number
@input_number_window.x = self.x + 8
@input_number_window.y = self.y + $game_temp.num_input_start * 32
end
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# If fade in
if @fade_in
self.contents_opacity += 24
if @input_number_window != nil
@input_number_window.contents_opacity += 24
end
if self.contents_opacity == 255
@fade_in = false
end
return
end
# If inputting number
if @input_number_window != nil
@input_number_window.update
# Confirm
if Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
$game_variables[$game_temp.num_input_variable_id] =
@input_number_window.number
$game_map.need_refresh = true
# Dispose of number input window
@input_number_window.dispose
@input_number_window = nil
terminate_message
end
return
end
# EDIT
if @choice_window != nil
@choice_window.update
if Input.trigger?(Input::LEFT)
unless @choice_window.moving?
@choice_window.move_left
end
end
if Input.trigger?(Input::RIGHT)
unless @choice_window.moving?
@choice_window.move_right
end
end
end
# /EDIT
# If message is being displayed
if @contents_showing
# If choice isn't being displayed, show pause sign
if $game_temp.choice_max == 0
self.pause = true
end
# Cancel
if Input.trigger?(Input::B)
if $game_temp.choice_max > 0 and $game_temp.choice_cancel_type > 0
$game_system.se_play($data_system.cancel_se)
$game_temp.choice_proc.call($game_temp.choice_cancel_type - 1)
terminate_message
end
end
# Confirm
if Input.trigger?(Input::C)
if $game_temp.choice_max > 0
$game_system.se_play($data_system.decision_se)
# EDIT
$game_temp.choice_proc.call(@choice_window.index)
# /EDIT
end
terminate_message
end
return
end
# If display wait message or choice exists when not fading out
if @fade_out == false and $game_temp.message_text != nil
@contents_showing = true
$game_temp.message_window_showing = true
reset_window
refresh
Graphics.frame_reset
self.visible = true
self.contents_opacity = 0
if @input_number_window != nil
@input_number_window.contents_opacity = 0
end
@fade_in = true
return
end
# If message which should be displayed is not shown, but window is visible
if self.visible
@fade_out = true
self.opacity -= 48
if self.opacity == 0
self.visible = false
@fade_out = false
$game_temp.message_window_showing = false
end
return
end
end
end
Background Windows add-on
class Window_Ring_Command < Window_Base
alias background_windows_initialize initialize
def initialize(x_pos, y_pos, commands, radius = 150.0)
@windows = []
background_windows_initialize(x_pos, y_pos, commands, radius = 150.0)
end
def refresh
self.contents.clear
unless @windows == []
for i in 0...@windows.size
@windows[i].dispose
@windows[i] = nil
end
@windows = []
end
if @moving != 0
@moving = (Math.abs(@moving) - 1) * (@moving/Math.abs(@moving))
end
max_item = @commands.size
pi_part = (2 * Math::PI) / max_item
for i in 0...max_item
x = (@radius * Math.sin((i * pi_part) + (@moving * (pi_part/Turn_Frames)))) + @x_pos
x = x.to_i
y = (@radius * Math.cos((i * pi_part) + (@moving * (pi_part/Turn_Frames)))) + @y_pos
y = y.to_i
@windows[@windows.size] = Window_Base.new(x, y, 158, 50)
draw_item(x, y, i)
end
end
def dispose
unless @windows == []
for i in 0...@windows.size
@windows[i].dispose
@windows[i] = nil
end
@windows = []
end
super
end
end