For years, I've seen the XRXS Ring Menu with additions by Dubealex and others. But never a pure version of the original version. So I decided to use my lycanthropic werewolf hunting skills to track down a pure version untouched by western editors.
And here it is.
Features
Its a RING menu
Contains a compact actor menu when selecting choices like Equip or Skill
Able to customize the icons
Script
I am providing BOTH the original version 1.2 (circa 2007 which Kazuki stated was abandoned) and an English version thanks to an hour's worth of wolfish translation.
#==============================================================================
# ■ Window_RingMenu
#==============================================================================
class Window_RingMenu < Window_Base
#--------------------------------------------------------------------------
# ○ クラス定数
#--------------------------------------------------------------------------
MODE_START = 1 # スタートアップアニメーション
MODE_WAIT = 2 # 待機
MODE_MOVER = 3 # 時計回り回転アニメーション
MODE_MOVEL = 4 # 反時計回り回転アニメーション
#--------------------------------------------------------------------------
# ○ アクセサ
#--------------------------------------------------------------------------
attr_accessor :index
attr_reader :commands
#--------------------------------------------------------------------------
# ● オブジェクト初期化
#--------------------------------------------------------------------------
def initialize( center_x, center_y )
super(-16, -16, 640+32, 480+32)
self.contents = Bitmap.new(width-32, height-32)
self.opacity = 0
self.back_opacity = 0
s1 = $data_system.words.item
s2 = $data_system.words.skill
s3 = $data_system.words.equip
s4 = "ステータス"
s5 = "セーブ"
s6 = "ゲーム終了"
@commands = [ s1, s2, s3, s4, s5, s6 ]
@item_max = 6
@index = 0
@items = [ ICON_ITEM, ICON_SKILL, ICON_EQUIP, ICON_STATUS, ICON_SAVE, ICON_EXIT ]
@disabled = [ false, false, false, false, false, false ]
@cx = center_x
@cy = center_y
setup_move_start
refresh
end
#--------------------------------------------------------------------------
# ● フレーム更新
#--------------------------------------------------------------------------
def update
super
refresh
end
#--------------------------------------------------------------------------
# ● 画面再描画
#--------------------------------------------------------------------------
def refresh
self.contents.clear
# 背景描画
if BACKGROUND_COLOR.alpha > 0
self.contents.fill_rect(0,0,640,480,BACKGROUND_COLOR)
end
# アイコンを描画
case @mode
when MODE_START
refresh_start
when MODE_WAIT
refresh_wait
when MODE_MOVER
refresh_move(1)
when MODE_MOVEL
refresh_move(0)
end
end
#--------------------------------------------------------------------------
# ○ 画面再描画(初期化時)
#--------------------------------------------------------------------------
def refresh_start
d1 = 2.0 * Math::PI / @item_max
d2 = 1.0 * Math::PI / STARTUP_FRAMES
r = RING_R - 1.0 * RING_R * @steps / STARTUP_FRAMES
for i in 0...@item_max
j = i - @index
d = d1 * j + d2 * @steps
x = @cx + ( r * Math.sin( d ) ).to_i
y = @cy - ( r * Math.cos( d ) ).to_i
draw_item(x, y, i)
end
@steps -= 1
if @steps < 1
@mode = MODE_WAIT
end
end
#--------------------------------------------------------------------------
# ○ 画面再描画(待機時)
#--------------------------------------------------------------------------
def refresh_wait
d = 2.0 * Math::PI / @item_max
for i in 0...@item_max
j = i - @index
x = @cx + ( RING_R * Math.sin( d * j ) ).to_i
y = @cy - ( RING_R * Math.cos( d * j ) ).to_i
draw_item(x, y, i)
end
end
#--------------------------------------------------------------------------
# ○ 画面再描画(回転時)
# mode : 0=反時計回り 1=時計回り
#--------------------------------------------------------------------------
def refresh_move( mode )
d1 = 2.0 * Math::PI / @item_max
d2 = d1 / MOVING_FRAMES
d2 *= -1 if mode != 0
for i in 0...@item_max
j = i - @index
d = d1 * j + d2 * @steps
x = @cx + ( RING_R * Math.sin( d ) ).to_i
y = @cy - ( RING_R * Math.cos( d ) ).to_i
draw_item(x, y, i)
end
@steps -= 1
if @steps < 1
@mode = MODE_WAIT
end
end
#--------------------------------------------------------------------------
# ● 項目の描画
# x :
# y :
# i : 項目番号
#--------------------------------------------------------------------------
def draw_item(x, y, i)
rect = Rect.new(0, 0, @items[i].width, @items[i].height)
x -= rect.width/2
y -= rect.height/2
if @index == i
self.contents.blt( x, y, @items[i], rect )
if @disabled[@index]
self.contents.blt( x, y, ICON_DISABLE, rect )
end
else
self.contents.blt( x, y, @items[i], rect, 128 )
if @disabled[@index]
self.contents.blt( x, y, ICON_DISABLE, rect, 128 )
end
end
end
#--------------------------------------------------------------------------
# ● 項目を無効にする
# index : 項目番号
#--------------------------------------------------------------------------
def disable_item(index)
@disabled[index] = true
end
#--------------------------------------------------------------------------
# ○ 初期化アニメーションの準備
#--------------------------------------------------------------------------
def setup_move_start
@mode = MODE_START
@steps = STARTUP_FRAMES
if SE_STARTUP != nil and SE_STARTUP != ""
Audio.se_play("Audio/SE/" + SE_STARTUP, 80, 100)
end
end
#--------------------------------------------------------------------------
# ○ 回転アニメーションの準備
#--------------------------------------------------------------------------
def setup_move_move(mode)
if mode == MODE_MOVER
@index -= 1
@index = @items.size - 1 if @index < 0
elsif mode == MODE_MOVEL
@index += 1
@index = 0 if @index >= @items.size
else
return
end
@mode = mode
@steps = MOVING_FRAMES
end
#--------------------------------------------------------------------------
# ○ アニメーション中かどうか
#--------------------------------------------------------------------------
def animation?
return @mode != MODE_WAIT
end
end
#==============================================================================
# ■ Window_MenuStatus
#------------------------------------------------------------------------------
# メニュー画面でパーティメンバーのステータスを表示するウィンドウです。
#==============================================================================
class Window_RingMenuStatus < Window_Selectable
attr_reader :max_index
#--------------------------------------------------------------------------
# ● オブジェクト初期化
#--------------------------------------------------------------------------
def initialize
@max_index = $game_party.actors.size - 1
h = 32 * (@max_index + 1) + 32
h = 416 if h > 416
x = 0
x = 456 if $game_player.screen_x < 200 + Window_RingMenu::RING_R
super(x, 64, 184, h)
self.contents = Bitmap.new(width - 32, $game_party.actors.size * 32)
refresh
self.active = false
self.index = -1
end
#--------------------------------------------------------------------------
# ● リフレッシュ
#--------------------------------------------------------------------------
def refresh
self.contents.clear
@item_max = $game_party.actors.size
for i in 0...$game_party.actors.size
x = 32
y = 32 * i
actor = $game_party.actors[i]
self.contents.draw_facesquare(actor.character_name, actor.character_hue,
4, y + 4 )
draw_actor_name(actor, x, y)
end
end
end
#==============================================================================
# ■ Scene_Menu
#------------------------------------------------------------------------------
# メニュー画面の処理を行うクラスです。
#==============================================================================
class Scene_Menu
#--------------------------------------------------------------------------
# ● オブジェクト初期化
# menu_index : コマンドのカーソル初期位置
#--------------------------------------------------------------------------
def initialize(menu_index = 0)
@menu_index = menu_index
end
#--------------------------------------------------------------------------
# ● メイン処理
#--------------------------------------------------------------------------
def main
# スプライトセットを作成
@spriteset = Spriteset_Map.new
# コマンドウィンドウを作成
bmp = RPG::Cache.character($game_party.actors[0].character_name, 0)
px = $game_player.screen_x
py = $game_player.screen_y - bmp.rect.height / 4 / 2
@command_window = Window_RingMenu.new(px,py)
@command_window.index = @menu_index
# パーティ人数が 0 人の場合
if $game_party.actors.size == 0
# アイテム、スキル、装備、ステータスを無効化
@command_window.disable_item(0)
@command_window.disable_item(1)
@command_window.disable_item(2)
@command_window.disable_item(3)
end
@command_window.z = 100
# セーブ禁止の場合
if $game_system.save_disabled
# セーブを無効にする
@command_window.disable_item(4)
end
# ステータスウィンドウを作成
@status_window = Window_RingMenuStatus.new
@status_window.z = 200
@status_window.visible = false
# ヘルプウィンドウを作成
@help_window = Window_Help.new
@help_window.set_text(@command_window.commands[@command_window.index],1)
# トランジション実行
Graphics.transition
# メインループ
loop do
# ゲーム画面を更新
Graphics.update
# 入力情報を更新
Input.update
# フレーム更新
update
# 画面が切り替わったらループを中断
if $scene != self
break
end
end
# トランジション準備
Graphics.freeze
# スプライトセットを解放
@spriteset.dispose
# ウィンドウを解放
@command_window.dispose
@status_window.dispose
@help_window.dispose
end
#--------------------------------------------------------------------------
# ● フレーム更新
#--------------------------------------------------------------------------
def update
# ウィンドウを更新
@command_window.update
@status_window.update
@help_window.update
# コマンドウィンドウがアクティブの場合: update_command を呼ぶ
if @command_window.active
update_command
return
end
# ステータスウィンドウがアクティブの場合: update_status を呼ぶ
if @status_window.active
update_status
return
end
end
#--------------------------------------------------------------------------
# ● フレーム更新 (コマンドウィンドウがアクティブの場合)
#--------------------------------------------------------------------------
def update_command
# B ボタンが押された場合
if Input.trigger?(Input::B)
# キャンセル SE を演奏
$game_system.se_play($data_system.cancel_se)
# マップ画面に切り替え
$scene = Scene_Map.new
return
end
# C ボタンが押された場合
if Input.trigger?(Input::C)
# パーティ人数が 0 人で、セーブ、ゲーム終了以外のコマンドの場合
if $game_party.actors.size == 0 and @command_window.index < 4
# ブザー SE を演奏
$game_system.se_play($data_system.buzzer_se)
return
end
# コマンドウィンドウのカーソル位置で分岐
case @command_window.index
when 0 # アイテム
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# アイテム画面に切り替え
$scene = Scene_Item.new
when 1 # スキル
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# ステータスウィンドウをアクティブにする
@command_window.active = false
@status_window.active = true
@status_window.visible = true
@status_window.index = 0
when 2 # 装備
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# ステータスウィンドウをアクティブにする
@command_window.active = false
@status_window.active = true
@status_window.visible = true
@status_window.index = 0
when 3 # ステータス
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# ステータスウィンドウをアクティブにする
@command_window.active = false
@status_window.active = true
@status_window.visible = true
@status_window.index = 0
when 4 # セーブ
# セーブ禁止の場合
if $game_system.save_disabled
# ブザー SE を演奏
$game_system.se_play($data_system.buzzer_se)
return
end
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# セーブ画面に切り替え
$scene = Scene_Save.new
when 5 # ゲーム終了
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# ゲーム終了画面に切り替え
$scene = Scene_End.new
end
return
end
# アニメーション中ならカーソルの処理を行わない
return if @command_window.animation?
# ↑or← ボタンが押された場合
if Input.press?(Input::UP) or Input.press?(Input::LEFT)
$game_system.se_play($data_system.cursor_se)
@command_window.setup_move_move(Window_RingMenu::MODE_MOVEL)
@help_window.set_text(@command_window.commands[@command_window.index],1)
return
end
# ↓or→ ボタンが押された場合
if Input.press?(Input::DOWN) or Input.press?(Input::RIGHT)
$game_system.se_play($data_system.cursor_se)
@command_window.setup_move_move(Window_RingMenu::MODE_MOVER)
@help_window.set_text(@command_window.commands[@command_window.index],1)
return
end
end
#--------------------------------------------------------------------------
# ● フレーム更新 (ステータスウィンドウがアクティブの場合)
#--------------------------------------------------------------------------
def update_status
# B ボタンが押された場合
if Input.trigger?(Input::B)
# キャンセル SE を演奏
$game_system.se_play($data_system.cancel_se)
# コマンドウィンドウをアクティブにする
@command_window.active = true
@status_window.active = false
@status_window.visible = false
@status_window.index = -1
return
end
# C ボタンが押された場合
if Input.trigger?(Input::C)
# コマンドウィンドウのカーソル位置で分岐
case @command_window.index
when 1 # スキル
# このアクターの行動制限が 2 以上の場合
if $game_party.actors[@status_window.index].restriction >= 2
# ブザー SE を演奏
$game_system.se_play($data_system.buzzer_se)
return
end
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# スキル画面に切り替え
$scene = Scene_Skill.new(@status_window.index)
when 2 # 装備
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# 装備画面に切り替え
$scene = Scene_Equip.new(@status_window.index)
when 3 # ステータス
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# ステータス画面に切り替え
$scene = Scene_Status.new(@status_window.index)
end
return
end
end
end
#==============================================================================
# ◇ 外部ライブラリ
#==============================================================================
class Bitmap
# ▼▲▼ XRXL 1. ライン・図形描写 ▼▲▼
#--------------------------------------------------------------------------
# ● ライン描画 by 桜雅 在土
#--------------------------------------------------------------------------
def draw_line(start_x, start_y, end_x, end_y, start_color, width = 1, end_color = start_color)
# 描写距離の計算。大きめに直角時の長さ。
distance = (start_x - end_x).abs + (start_y - end_y).abs
# 描写開始
if end_color == start_color
for i in 1..distance
x = (start_x + 1.0 * (end_x - start_x) * i / distance).to_i
y = (start_y + 1.0 * (end_y - start_y) * i / distance).to_i
if width == 1
self.set_pixel(x, y, start_color)
else
self.fill_rect(x, y, width, width, start_color)
end
end
else
for i in 1..distance
x = (start_x + 1.0 * (end_x - start_x) * i / distance).to_i
y = (start_y + 1.0 * (end_y - start_y) * i / distance).to_i
r = start_color.red * (distance-i)/distance + end_color.red * i/distance
g = start_color.green * (distance-i)/distance + end_color.green * i/distance
b = start_color.blue * (distance-i)/distance + end_color.blue * i/distance
a = start_color.alpha * (distance-i)/distance + end_color.alpha * i/distance
if width == 1
self.set_pixel(x, y, Color.new(r, g, b, a))
else
self.fill_rect(x, y, width, width, Color.new(r, g, b, a))
end
end
end
end
#--------------------------------------------------------------------------
# ● 多角形の描画(塗りつぶしなし) by 和希
# peaks : 頂点座標の配列 [[x1,y1],[x2,y2],[x3,y3], ... ]
# color : 線の色
# width : 線の幅
#--------------------------------------------------------------------------
def draw_polygon(peaks, color, width = 1)
# 辺(=頂点)の個数分だけ辺を描く
for i in 0 ... (peaks.size - 1)
# 頂点同士を線で結ぶ
draw_line( peaks[i][0], peaks[i][1], peaks[i+1][0], peaks[i+1][1], color, width )
end
# 最後の頂点と最初の頂点を結ぶ
draw_line( peaks[peaks.size - 1][0], peaks[peaks.size - 1][1], peaks[0][0], peaks[0][1], color, width )
end
# ▼▲▼ XRXL 2. ビットマップ/アイコン描写 ▼▲▼
#--------------------------------------------------------------------------
# ● 顔&枠の描画 by 桜雅 在土
# character_name : 描写に利用するキャラクターグラフィック
# character_hue : 描写の色合い
# x : 描画先 X 座標
# y : 描画先 Y 座標
#--------------------------------------------------------------------------
def draw_facesquare(character_name, character_hue, x, y, size = 24)
bitmap = RPG::Cache.character(character_name, character_hue)
src_rect = Rect.new((bitmap.width/4 - size)/2, 0, size, size)
self.blt(x, y, bitmap, src_rect)
self.draw_polygon([[x,y],[x+size,y],[x+size,y+size],[x,y+size]], Color.new(255,255,255,128))
end
end
English Translated Version
Code:
# ▼▲▼ XRXS_MP 6. Ring Menu Implementation ver.1.2 ▼▲▼
# By Kazuki
#==============================================================================
# □ Customization Points
#==============================================================================
class Window_RingMenu < Window_Base
STARTUP_FRAMES = 20 # Number of frames in the initial animation
MOVING_FRAMES = 5 # The number of frames when rotating the ring
RING_R = 64 # Radius of the ring
SE_STARTUP = "056-Right02" # The sound effect played when opening the menu
ICON_ITEM = RPG::Cache.icon("034-Item03") # Icons in the "Items" Menu
ICON_SKILL = RPG::Cache.icon("044-Skill01") # Icons in the "Skills" Menu
ICON_EQUIP = RPG::Cache.icon("001-Weapon01") # "Equipment" Menu Icon
ICON_STATUS = RPG::Cache.icon("050-Skill07") # "Status" Menu Icons
ICON_SAVE = RPG::Cache.icon("038-Item07") # "Save" Menu Icon
ICON_EXIT = RPG::Cache.icon("046-Skill03") # "Exit" Menu Icon
ICON_DISABLE= RPG::Cache.icon("") # Icons for Prohibited Items
BACKGROUND_COLOR = Color.new(0xcc,0x99,0x33,0x3f)
end
###############################################################################
# Ring Menu Implementation Script Ver. 1.2
# writen by Kazuki
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# ▽ Introduction
# 0. Please install "XRXL 2. Bitmap/Icon Rendering" beforehand.
# 1. Copy this script into a new section created above the Main section.
# 2. Inside the double quotas (`""`) of the sevenRPG::Cache.icon("") entries
# located at the top of `Window_RingMenu, enter the icon for each command.
# Follow as they are described in the comments to the right.
# The "Disabled" icon at the bottom is an icon that overlays atop the
# menu icons that cannot be selected. Recommended is something like: φ
# 3. Inside the "" of the TSE_STARTUP value, place the sound effect that you
# want to sound when the menu opens
# ▽ For those comfortable working with scripts
# Since I built this with the sole goal of getting something—anything—up and
# running (yeah, I set the bar pretty low!), the coordinate alignment and
# similar details are still incomplete.
# We added a process to obtain the actor's screen coordinates more accurately,
# and the position of the actor list.
# I feel like if you tweak things—such as making changes or adjusting the text
# display—it will turn out really nicely.
###############################################################################
#==============================================================================
# ■ Window_RingMenu
#==============================================================================
class Window_RingMenu < Window_Base
#--------------------------------------------------------------------------
# ○ Class Constants
#--------------------------------------------------------------------------
MODE_START = 1 # Startup Animation
MODE_WAIT = 2 # Stand By
MODE_MOVER = 3 # Clockwise Rotation Animation
MODE_MOVEL = 4 # Counter-clockwise Rotation Animation
#--------------------------------------------------------------------------
# ○ Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :index
attr_reader :commands
#--------------------------------------------------------------------------
# ● Object Initialization
#--------------------------------------------------------------------------
def initialize( center_x, center_y )
super(-16, -16, 640+32, 480+32)
self.contents = Bitmap.new(width-32, height-32)
self.opacity = 0
self.back_opacity = 0
s1 = $data_system.words.item
s2 = $data_system.words.skill
s3 = $data_system.words.equip
s4 = "Status"
s5 = "Save"
s6 = "Game Over"
@commands = [ s1, s2, s3, s4, s5, s6 ]
@item_max = 6
@index = 0
@items = [ ICON_ITEM, ICON_SKILL, ICON_EQUIP, ICON_STATUS, ICON_SAVE, ICON_EXIT ]
@disabled = [ false, false, false, false, false, false ]
@cx = center_x
@cy = center_y
setup_move_start
refresh
end
#--------------------------------------------------------------------------
# ● Frame Update
#--------------------------------------------------------------------------
def update
super
refresh
end
#--------------------------------------------------------------------------
# ● Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
# Draw background
if BACKGROUND_COLOR.alpha > 0
self.contents.fill_rect(0,0,640,480,BACKGROUND_COLOR)
end
# Draw Icon
case @mode
when MODE_START
refresh_start
when MODE_WAIT
refresh_wait
when MODE_MOVER
refresh_move(1)
when MODE_MOVEL
refresh_move(0)
end
end
#--------------------------------------------------------------------------
# ○ Screen redraw (at initialization)
#--------------------------------------------------------------------------
def refresh_start
d1 = 2.0 * Math::PI / @item_max
d2 = 1.0 * Math::PI / STARTUP_FRAMES
r = RING_R - 1.0 * RING_R * @steps / STARTUP_FRAMES
for i in 0...@item_max
j = i - @index
d = d1 * j + d2 * @steps
x = @cx + ( r * Math.sin( d ) ).to_i
y = @cy - ( r * Math.cos( d ) ).to_i
draw_item(x, y, i)
end
@steps -= 1
if @steps < 1
@mode = MODE_WAIT
end
end
#--------------------------------------------------------------------------
# ○ Screen redraw (standby)
#--------------------------------------------------------------------------
def refresh_wait
d = 2.0 * Math::PI / @item_max
for i in 0...@item_max
j = i - @index
x = @cx + ( RING_R * Math.sin( d * j ) ).to_i
y = @cy - ( RING_R * Math.cos( d * j ) ).to_i
draw_item(x, y, i)
end
end
#--------------------------------------------------------------------------
# ○ Screen Redraw (on Rotation)
# mode : 0=Counter-clockwise 1=Clockwise
#--------------------------------------------------------------------------
def refresh_move( mode )
d1 = 2.0 * Math::PI / @item_max
d2 = d1 / MOVING_FRAMES
d2 *= -1 if mode != 0
for i in 0...@item_max
j = i - @index
d = d1 * j + d2 * @steps
x = @cx + ( RING_R * Math.sin( d ) ).to_i
y = @cy - ( RING_R * Math.cos( d ) ).to_i
draw_item(x, y, i)
end
@steps -= 1
if @steps < 1
@mode = MODE_WAIT
end
end
#--------------------------------------------------------------------------
# ● Draw Item
# x :
# y :
# i : Item number
#--------------------------------------------------------------------------
def draw_item(x, y, i)
rect = Rect.new(0, 0, @items[i].width, @items[i].height)
x -= rect.width/2
y -= rect.height/2
if @index == i
self.contents.blt( x, y, @items[i], rect )
if @disabled[@index]
self.contents.blt( x, y, ICON_DISABLE, rect )
end
else
self.contents.blt( x, y, @items[i], rect, 128 )
if @disabled[@index]
self.contents.blt( x, y, ICON_DISABLE, rect, 128 )
end
end
end
#--------------------------------------------------------------------------
# ● Disable Item
# index : Item number
#--------------------------------------------------------------------------
def disable_item(index)
@disabled[index] = true
end
#--------------------------------------------------------------------------
# ○ Preparing the Initialization Animation
#--------------------------------------------------------------------------
def setup_move_start
@mode = MODE_START
@steps = STARTUP_FRAMES
if SE_STARTUP != nil and SE_STARTUP != ""
Audio.se_play("Audio/SE/" + SE_STARTUP, 80, 100)
end
end
#--------------------------------------------------------------------------
# ○ Preparing the Rotation Animation
#--------------------------------------------------------------------------
def setup_move_move(mode)
if mode == MODE_MOVER
@index -= 1
@index = @items.size - 1 if @index < 0
elsif mode == MODE_MOVEL
@index += 1
@index = 0 if @index >= @items.size
else
return
end
@mode = mode
@steps = MOVING_FRAMES
end
#--------------------------------------------------------------------------
# ○ Whether currently animating
#--------------------------------------------------------------------------
def animation?
return @mode != MODE_WAIT
end
end
#==============================================================================
# ■ Window_MenuStatus
#------------------------------------------------------------------------------
# This window displays party member status on the menu screen.
#==============================================================================
class Window_RingMenuStatus < Window_Selectable
attr_reader :max_index
#--------------------------------------------------------------------------
# ● Object Initialization
#--------------------------------------------------------------------------
def initialize
@max_index = $game_party.actors.size - 1
h = 32 * (@max_index + 1) + 32
h = 416 if h > 416
x = 0
x = 456 if $game_player.screen_x < 200 + Window_RingMenu::RING_R
super(x, 64, 184, h)
self.contents = Bitmap.new(width - 32, $game_party.actors.size * 32)
refresh
self.active = false
self.index = -1
end
#--------------------------------------------------------------------------
# ● Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
@item_max = $game_party.actors.size
for i in 0...$game_party.actors.size
x = 32
y = 32 * i
actor = $game_party.actors[i]
self.contents.draw_facesquare(actor.character_name, actor.character_hue,
4, y + 4 )
draw_actor_name(actor, x, y)
end
end
end
#==============================================================================
# ■ Scene_Menu
#------------------------------------------------------------------------------
# This class performs menu screen processing.
#==============================================================================
class Scene_Menu
#--------------------------------------------------------------------------
# ● Object Initialization
# menu_index : command cursor's initial position
#--------------------------------------------------------------------------
def initialize(menu_index = 0)
@menu_index = menu_index
end
#--------------------------------------------------------------------------
# ● Main Processing
#--------------------------------------------------------------------------
def main
# Make spriteset
@spriteset = Spriteset_Map.new
# Make command window
bmp = RPG::Cache.character($game_party.actors[0].character_name, 0)
px = $game_player.screen_x
py = $game_player.screen_y - bmp.rect.height / 4 / 2
@command_window = Window_RingMenu.new(px,py)
@command_window.index = @menu_index
# If number of party members is 0
if $game_party.actors.size == 0
# Disable items, skills, equipment, and status
@command_window.disable_item(0)
@command_window.disable_item(1)
@command_window.disable_item(2)
@command_window.disable_item(3)
end
@command_window.z = 100
# If save is forbidden
if $game_system.save_disabled
# Disable save
@command_window.disable_item(4)
end
# Make status window
@status_window = Window_RingMenuStatus.new
@status_window.z = 200
@status_window.visible = false
# Make help window
@help_window = Window_Help.new
@help_window.set_text(@command_window.commands[@command_window.index],1)
# Execute transition
Graphics.transition
# Main loop
loop do
# Update game screen
Graphics.update
# Update input information
Input.update
# Frame update
update
# Abort loop if screen is changed
if $scene != self
break
end
end
# Prepare for transition
Graphics.freeze
# Dispose of spriteset
@spriteset.dispose
# Dispose of windows
@command_window.dispose
@status_window.dispose
@help_window.dispose
end
#--------------------------------------------------------------------------
# ● Frame Update
#--------------------------------------------------------------------------
def update
# Update windows
@command_window.update
@status_window.update
@help_window.update
# If command window is active: call update_command
if @command_window.active
update_command
return
end
# If status window is active: call update_status
if @status_window.active
update_status
return
end
end
#--------------------------------------------------------------------------
# ● Frame Update (when command window is active)
#--------------------------------------------------------------------------
def update_command
# If B button was pressed
if Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
# Switch to map screen
$scene = Scene_Map.new
return
end
# If C button was pressed
if Input.trigger?(Input::C)
# If command other than save or end game, and party members = 0
if $game_party.actors.size == 0 and @command_window.index < 4
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
end
# Branch by command window cursor position
case @command_window.index
when 0 # item
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Switch to item screen
$scene = Scene_Item.new
when 1 # skill
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Make status window active
@command_window.active = false
@status_window.active = true
@status_window.visible = true
@status_window.index = 0
when 2 # equipment
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Make status window active
@command_window.active = false
@status_window.active = true
@status_window.visible = true
@status_window.index = 0
when 3 # status
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Make status window active
@command_window.active = false
@status_window.active = true
@status_window.visible = true
@status_window.index = 0
when 4 # save
# If saving is forbidden
if $game_system.save_disabled
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
end
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Switch to save screen
$scene = Scene_Save.new
when 5 # Game Over
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Switch to end game screen
$scene = Scene_End.new
end
return
end
# Do not process the cursor while an animation is in progress.
return if @command_window.animation?
# ↑or← ボタンが押された場合
if Input.press?(Input::UP) or Input.press?(Input::LEFT)
$game_system.se_play($data_system.cursor_se)
@command_window.setup_move_move(Window_RingMenu::MODE_MOVEL)
@help_window.set_text(@command_window.commands[@command_window.index],1)
return
end
# If the ↓ or → button is pressed
if Input.press?(Input::DOWN) or Input.press?(Input::RIGHT)
$game_system.se_play($data_system.cursor_se)
@command_window.setup_move_move(Window_RingMenu::MODE_MOVER)
@help_window.set_text(@command_window.commands[@command_window.index],1)
return
end
end
#--------------------------------------------------------------------------
# ● Frame Update (when status window is active)
#--------------------------------------------------------------------------
def update_status
# If B button was pressed
if Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
# Make command window active
@command_window.active = true
@status_window.active = false
@status_window.visible = false
@status_window.index = -1
return
end
# If C button was pressed
if Input.trigger?(Input::C)
# Branch by command window cursor position
case @command_window.index
when 1 # skill
# If this actor's action limit is 2 or more
if $game_party.actors[@status_window.index].restriction >= 2
# Play buzzer SE
$game_system.se_play($data_system.buzzer_se)
return
end
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Switch to skill screen
$scene = Scene_Skill.new(@status_window.index)
when 2 # equipment
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Switch to equipment screen
$scene = Scene_Equip.new(@status_window.index)
when 3 # status
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Switch to status screen
$scene = Scene_Status.new(@status_window.index)
end
return
end
end
end
#==============================================================================
# ◇ External Libraries
#==============================================================================
class Bitmap
# ▼▲▼ XRXL 1. Line and Shape Drawing ▼▲▼
#--------------------------------------------------------------------------
# ● ライン描画 by 桜雅 在土
#--------------------------------------------------------------------------
def draw_line(start_x, start_y, end_x, end_y, start_color, width = 1, end_color = start_color)
# Calculation of rendering distance. A generous estimate for the length at a right angle.
distance = (start_x - end_x).abs + (start_y - end_y).abs
# Start drawing
if end_color == start_color
for i in 1..distance
x = (start_x + 1.0 * (end_x - start_x) * i / distance).to_i
y = (start_y + 1.0 * (end_y - start_y) * i / distance).to_i
if width == 1
self.set_pixel(x, y, start_color)
else
self.fill_rect(x, y, width, width, start_color)
end
end
else
for i in 1..distance
x = (start_x + 1.0 * (end_x - start_x) * i / distance).to_i
y = (start_y + 1.0 * (end_y - start_y) * i / distance).to_i
r = start_color.red * (distance-i)/distance + end_color.red * i/distance
g = start_color.green * (distance-i)/distance + end_color.green * i/distance
b = start_color.blue * (distance-i)/distance + end_color.blue * i/distance
a = start_color.alpha * (distance-i)/distance + end_color.alpha * i/distance
if width == 1
self.set_pixel(x, y, Color.new(r, g, b, a))
else
self.fill_rect(x, y, width, width, Color.new(r, g, b, a))
end
end
end
end
#--------------------------------------------------------------------------
# ● Drawing a Polygon (Unfilled) by Kazuki
# peaks : Array of vertex coordinates [[x1,y1],[x2,y2],[x3,y3], ... ]
# color : Line Color
# width : Line width
#--------------------------------------------------------------------------
def draw_polygon(peaks, color, width = 1)
# Draw a number of edges equal to the number of edges (or vertices).
for i in 0 ... (peaks.size - 1)
# Connect the vertices with lines.
draw_line( peaks[i][0], peaks[i][1], peaks[i+1][0], peaks[i+1][1], color, width )
end
# Connect the last vertex to the first vertex.
draw_line( peaks[peaks.size - 1][0], peaks[peaks.size - 1][1], peaks[0][0], peaks[0][1], color, width )
end
# ▼▲▼ XRXL 2. Bitmap/Icon Rendering ▼▲▼
#--------------------------------------------------------------------------
# ● Face and frame drawing by Ouga Zaitou
# character_name : Character Graphics Used for Depiction
# character_hue : The Hue of the Character
# x : Drawing Destination X-Coordinate
# y : Drawing Destination Y-Coordinate
#--------------------------------------------------------------------------
def draw_facesquare(character_name, character_hue, x, y, size = 24)
bitmap = RPG::Cache.character(character_name, character_hue)
src_rect = Rect.new((bitmap.width/4 - size)/2, 0, size, size)
self.blt(x, y, bitmap, src_rect)
self.draw_polygon([[x,y],[x+size,y],[x+size,y+size],[x,y+size]], Color.new(255,255,255,128))
end
end