| 赞 | 46 |
| VIP | |
| 好人卡 | |
| 积分 | 329 |
| 经验 | |
| 最后登录 | 2026-2-3 |
| 在线时间 | 248 小时 |
- 梦石
- 24
- 星屑
- 8942
- 在线时间
- 248 小时
- 注册时间
- 2020-12-4
- 回帖
- 259
  
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有账号?注册会员
×
本帖最后由 纯属小虫 于 2023-4-27 15:32 编辑
XP的默认物品排序方式是按照 物品or技能 的id大小来依次排列的,
如果要在游戏中营造比较好的物品栏视觉效果,同类物品的相邻排序则显得十分重要
比如,如果要让消耗品排列在物品栏的最前端,那么就需要让消耗物品的ID排前,并且在游戏制作的时候就确定好可能的物品类型,如:药品、食品、宝石、皮毛。。。。。
如果处理得恰当,并且物品类型比较确定,那么在游戏中将会有比较好的排列效果,找物品的时候也相对容易。
不过,这种处理方式的缺点就是灵活性缺失。如果制作初期没有将数据库中的内容定好框架,或是在后期某一类型的物品过多,导致留空不足,就只能放在之后,没法按照始定的排列逻辑添加新品了。
如图,我在制作之初忘记给数据库留出足够的空位来放置同类武器。如果我还想添加新的匕首类武器,那便只能在后面的数据库添加,游戏背包中匕首类武器的位置便不是相邻的,如果背包里的武器很多,那找武器将是一件很头疼的事。
处理物品排列最简单的方式莫过于使用背包分类脚本了
为每一件物品定义类型,那么在类型背包中,同类的物品自然会被排列在一起;此外,有分类标签的加持,找物品将是一件很简单的事情。数据库中添加新物品的时候也不用太过考虑顺序的问题了。
[fold=物品分类脚本——复制自RMXP图书馆][pre lang="ruby"]#==============================================================================
# 本脚本来自www.66RPG.com,使用和转载请保留此信息
#==============================================================================
#==============================================================================
# ■ Harts_Window_ItemTitle
#------------------------------------------------------------------------------
# アイテム画面で、タイトルを表示するウィンドウ。
#==============================================================================
class Harts_Window_ItemTitle < Window_Base
#--------------------------------------------------------------------------
# ● オブジェクト初期化
#--------------------------------------------------------------------------
def initialize
super(0, 0, 160, 64)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.clear
self.contents.font.color = normal_color
self.contents.draw_text(4, 0, 120, 32, $data_system.words.item, 1)
end
end
#==============================================================================
# ■ Harts_Window_ItemCommand
#------------------------------------------------------------------------------
# アイテムの種別選択を行うウィンドウです。
#==============================================================================
class Harts_Window_ItemCommand < Window_Selectable
#--------------------------------------------------------------------------
# ● オブジェクト初期化
#--------------------------------------------------------------------------
def initialize
super(0, 64, 160, 288)
self.contents = Bitmap.new(width - 32, height - 32)
@item_max = 8
@commands = ["一般用", "战斗用", $data_system.words.weapon, $data_system.words.armor1, $data_system.words.armor2, $data_system.words.armor3, $data_system.words.armor4, "特殊道具"]
refresh
self.index = 0
end
#--------------------------------------------------------------------------
# ● リフレッシュ
#--------------------------------------------------------------------------
def refresh
self.contents.clear
for i in 0...@item_max
draw_item(i, normal_color)
end
end
#--------------------------------------------------------------------------
# ● 項目の描画
# index : 項目番号
# color : 文字色
#--------------------------------------------------------------------------
def draw_item(index, color)
self.contents.font.color = color
y = index * 32
self.contents.draw_text(4, y, 128, 32, @commands[index])
end
#--------------------------------------------------------------------------
# ● ヘルプテキスト更新
#--------------------------------------------------------------------------
def update_help
case self.index
when 0
@text = @commands[0]
when 1
@text = @commands[1]
when 2
@text = @commands[2]
when 3
@text = @commands[3]
when 4
@text = @commands[4]
when 5
@text = @commands[5]
when 6
@text = @commands[6]
when 7
@text = @commands[7]
end
@help_window.set_text(@text)
end
end
#==============================================================================
# ■ Window_Item
#------------------------------------------------------------------------------
# アイテム画面で、所持アイテムの一覧を表示するウィンドウです。
#==============================================================================
class Harts_Window_ItemList < Window_Selectable
#--------------------------------------------------------------------------
# ● オブジェクト初期化
#--------------------------------------------------------------------------
def initialize
super(160, 0, 480, 416)
refresh
self.index = 0
end
#--------------------------------------------------------------------------
# ● アイテムの取得
#--------------------------------------------------------------------------
def item
return @data[self.index]
end
#--------------------------------------------------------------------------
# ● リフレッシュ
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
end
#--------------------------------------------------------------------------
# ● アイテム一覧設定
# command : 選択中のコマンド
#--------------------------------------------------------------------------
def set_item(command)
refresh
case command
when 0
for i in 1...$data_items.size
if ($data_items.occasion == 0 or $data_items.occasion == 2) and $game_party.item_number(i) > 0
@data.push($data_items)
end
end
when 1
for i in 1...$data_items.size
if ($data_items.occasion == 1 and $game_party.item_number(i) > 0)
@data.push($data_items)
end
end
when 2
for i in 1...$data_weapons.size
if $game_party.weapon_number(i) > 0
@data.push($data_weapons)
end
end
when 3
for i in 1...$data_armors.size
if $data_armors.kind == 0 and $game_party.armor_number(i) > 0
@data.push($data_armors)
end
end
when 4
for i in 1...$data_armors.size
if $data_armors.kind == 1 and $game_party.armor_number(i) > 0
@data.push($data_armors)
end
end
when 5
for i in 1...$data_armors.size
if $data_armors.kind == 2 and $game_party.armor_number(i) > 0
@data.push($data_armors)
end
end
when 6
for i in 1...$data_armors.size
if $data_armors.kind == 3 and $game_party.armor_number(i) > 0
@data.push($data_armors)
end
end
when 7
for i in 1...$data_items.size
if $data_items.occasion == 3 and $game_party.item_number(i) > 0
@data.push($data_items)
end
end
end
# 項目数が 0 でなければビットマップを作成し、全項目を描画
@item_max = @data.size
if @item_max > 0
self.contents = Bitmap.new(width - 32, row_max * 32)
self.contents.clear
for i in 0...@item_max
draw_item(i)
end
end
end
#--------------------------------------------------------------------------
# ● 種類別アイテム数の取得
#--------------------------------------------------------------------------
def item_number
return @item_max
end
#--------------------------------------------------------------------------
# ● 項目の描画
# index : 項目番号
#--------------------------------------------------------------------------
def draw_item(index)
item = @data[index]
case item
when RPG::Item
number = $game_party.item_number(item.id)
when RPG::Weapon
number = $game_party.weapon_number(item.id)
when RPG::Armor
number = $game_party.armor_number(item.id)
end
if item.is_a?(RPG::Item) and
$game_party.item_can_use?(item.id)
self.contents.font.color = normal_color
else
self.contents.font.color = disabled_color
end
x = 4
y = index * 32
bitmap = RPG::Cache.icon(item.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)
self.contents.draw_text(x + 28, y, 212, 32, item.name, 0)
self.contents.draw_text(x + 400, y, 16, 32, ":", 1)
self.contents.draw_text(x + 416, y, 24, 32, number.to_s, 2)
end
#--------------------------------------------------------------------------
# ● ヘルプテキスト更新
#--------------------------------------------------------------------------
def update_help
@help_window.set_text(self.item == nil ? "" : self.item.description)
end
end
#==============================================================================
# ■ Harts_Scene_Item
#------------------------------------------------------------------------------
# アイテム画面の処理を行うクラスです。再定義
#==============================================================================
class Scene_Item
#--------------------------------------------------------------------------
# ● メイン処理
#--------------------------------------------------------------------------
def main
# タイトルウィンドウを作成
@itemtitle_window = Harts_Window_ItemTitle.new
#コマンドウィンドウを作成
@itemcommand_window = Harts_Window_ItemCommand.new
@command_index = @itemcommand_window.index
#アイテムウィンドウを作成
@itemlist_window = Harts_Window_ItemList.new
@itemlist_window.active = false
#ヘルプウィンドウを作成
@help_window = Window_Help.new
@help_window.x = 0
@help_window.y = 416
# ヘルプウィンドウを関連付け
@itemcommand_window.help_window = @help_window
@itemlist_window.help_window = @help_window
# ターゲットウィンドウを作成 (不可視?非アクティブに設定)
@target_window = Window_Target.new
@target_window.visible = false
@target_window.active = false
# アイテムウィンドウ内容表示
@itemlist_window.set_item(@command_index)
# トランジション実行
Graphics.transition
# メインループ
loop do
# ゲーム画面を更新
Graphics.update
# 入力情報を更新
Input.update
# フレーム更新
update
# 画面が切り替わったらループを中断
if $scene != self
break
end
end
# トランジション準備
Graphics.freeze
# ウィンドウを解放
@itemtitle_window.dispose
@itemcommand_window.dispose
@itemlist_window.dispose
@help_window.dispose
@target_window.dispose
end
#--------------------------------------------------------------------------
# ● フレーム更新
#--------------------------------------------------------------------------
def update
# ウィンドウを更新
@itemtitle_window.update
@itemcommand_window.update
@itemlist_window.update
@help_window.update
@target_window.update
if @command_index != @itemcommand_window.index
@command_index = @itemcommand_window.index
@itemlist_window.set_item(@command_index)
end
# コマンドウィンドウがアクティブの場合: update_itemcommand を呼ぶ
if @itemcommand_window.active
update_itemcommand
return
end
# アイテムウィンドウがアクティブの場合: update_itemlist を呼ぶ
if @itemlist_window.active
update_itemlist
return
end
# ターゲットウィンドウがアクティブの場合: update_target を呼ぶ
if @target_window.active
update_target
return
end
end
#--------------------------------------------------------------------------
# ● フレーム更新 (コマンドウィンドウがアクティブの場合)
#--------------------------------------------------------------------------
def update_itemcommand
# B ボタンが押された場合
if Input.trigger?(Input::B)
# キャンセル SE を演奏
$game_system.se_play($data_system.cancel_se)
# メニュー画面に切り替え
$scene = Scene_Menu.new(0)
return
end
# C ボタンが押された場合
if Input.trigger?(Input::C)
# 選択中のコマンドのアイテムがない場合
if @itemlist_window.item_number == 0
# ブザー SE を演奏
$game_system.se_play($data_system.buzzer_se)
return
end
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# アイテムウィンドウをアクティブにする
@itemcommand_window.active = false
@itemlist_window.active = true
@itemlist_window.index = 0
return
end
end
#--------------------------------------------------------------------------
# ● フレーム更新 (アイテムウィンドウがアクティブの場合)
#--------------------------------------------------------------------------
def update_itemlist
# B ボタンが押された場合
if Input.trigger?(Input::B)
# キャンセル SE を演奏
$game_system.se_play($data_system.cancel_se)
# アイテムウィンドウをアクティブにする
@itemcommand_window.active = true
@itemlist_window.active = false
@itemlist_window.index = 0
@itemcommand_window.index = @command_index
return
end
# C ボタンが押された場合
if Input.trigger?(Input::C)
# アイテムウィンドウで現在選択されているデータを取得
@item = @itemlist_window.item
# 使用アイテムではない場合
unless @item.is_a?(RPG::Item)
# ブザー SE を演奏
$game_system.se_play($data_system.buzzer_se)
return
end
# 使用できない場合
unless $game_party.item_can_use?(@item.id)
# ブザー SE を演奏
$game_system.se_play($data_system.buzzer_se)
return
end
# 決定 SE を演奏
$game_system.se_play($data_system.decision_se)
# 効果範囲が味方の場合
if @item.scope >= 3
# ターゲットウィンドウをアクティブ化
@itemlist_window.active = false
@target_window.x = 304
@target_window.visible = true
@target_window.active = true
# 効果範囲 (単体/全体) に応じてカーソル位置を設定
if @item.scope == 4 || @item.scope == 6
@target_window.index = -1
else
@target_window.index = 0
end
# 効果範囲が味方以外の場合
else
# コモンイベント ID が有効の場合
if @item.common_event_id > 0
# コモンイベント呼び出し予約
$game_temp.common_event_id = @item.common_event_id
# アイテムの使用時 SE を演奏
$game_system.se_play(@item.menu_se)
# 消耗品の場合
if @item.consumable
# 使用したアイテムを 1 減らす
$game_party.lose_item(@item.id, 1)
# アイテムウィンドウの項目を再描画
@itemlist_window.draw_item(@itemlist_window.index)
end
# マップ画面に切り替え
$scene = Scene_Map.new
return
end
end
return
end
end
#--------------------------------------------------------------------------
# ● フレーム更新 (ターゲットウィンドウがアクティブの場合)
#--------------------------------------------------------------------------
def update_target
# B ボタンが押された場合
if Input.trigger?(Input::B)
# キャンセル SE を演奏
$game_system.se_play($data_system.cancel_se)
# アイテム切れなどで使用できなくなった場合
unless $game_party.item_can_use?(@item.id)
# アイテムウィンドウの内容を再作成
@itemlist_window.refresh
end
# ターゲットウィンドウを消去
@itemlist_window.active = true
@target_window.visible = false
@target_window.active = false
@itemlist_window.set_item(@command_index)
return
end
# C ボタンが押された場合
if Input.trigger?(Input::C)
# アイテムを使い切った場合
if $game_party.item_number(@item.id) == 0
# ブザー SE を演奏
$game_system.se_play($data_system.buzzer_se)
return
end
# ターゲットが全体の場合
if @target_window.index == -1
# パーティ全体にアイテムの使用効果を適用
used = false
for i in $game_party.actors
used |= i.item_effect(@item)
end
end
# ターゲットが単体の場合
if @target_window.index >= 0
# ターゲットのアクターにアイテムの使用効果を適用
target = $game_party.actors[@target_window.index]
used = target.item_effect(@item)
end
# アイテムを使った場合
if used
# アイテムの使用時 SE を演奏
$game_system.se_play(@item.menu_se)
# 消耗品の場合
if @item.consumable
# 使用したアイテムを 1 減らす
$game_party.lose_item(@item.id, 1)
# アイテムウィンドウの項目を再描画
@itemlist_window.draw_item(@itemlist_window.index)
@itemlist_window.set_item(@command_index)
end
# ターゲットウィンドウの内容を再作成
@target_window.refresh
# 全滅の場合
if $game_party.all_dead?
# ゲームオーバー画面に切り替え
$scene = Scene_Gameover.new
return
end
# コモンイベント ID が有効の場合
if @item.common_event_id > 0
# コモンイベント呼び出し予約
$game_temp.common_event_id = @item.common_event_id
# マップ画面に切り替え
$scene = Scene_Map.new
return
end
end
# アイテムを使わなかった場合
unless used
# ブザー SE を演奏
$game_system.se_play($data_system.buzzer_se)
end
return
end
end
end
#==============================================================================
# 本脚本来自www.66RPG.com,使用和转载请保留此信息
#==============================================================================[/pre][/fold]
对于技能而言,也是同理。当角色技能过多时,可以将技能分类为 【回复】 【进攻】 【加持】 等...
但是,分类能够解决整体问题,却没办法解决更细致的问题。
比如,我将背包分为了 【素材】【消耗品】【情报】【武器】【头盔】【护甲】【饰品】....
但事实上,【素材】里还有 (宝石)(植物)(皮革)...... 【武器】里还有(匕首)(剑)(钝器).....
如果把大类再进行子类划分,则会显得很复杂。而且在名字后面添加一个类别备注已经很麻烦了,如果再添加一个子类备注,想想就头疼。
或许,我们便可以找到跟物品排序直接关联的脚本,在窗口中的items描绘上对其直接篡改:
[fold=以 背包 窗口 为例][pre lang="ruby"]#==============================================================================
# ■ Window_Item
#------------------------------------------------------------------------------
# 物品画面、战斗画面、显示浏览物品的窗口。
#==============================================================================
class Window_Item < Window_Selectable
#--------------------------------------------------------------------------
# ● 刷新
#--------------------------------------------------------------------------
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
# 添加物品
for i in 1...$data_items.size
if $game_party.item_number(i) > 0
@data.push($data_items)
end
end
# 在战斗中以外添加武器、防具
unless $game_temp.in_battle
for i in 1...$data_weapons.size
if $game_party.weapon_number(i) > 0
@data.push($data_weapons)
end
end
for i in 1...$data_armors.size
if $game_party.armor_number(i) > 0
@data.push($data_armors)
end
end
end
# 如果项目数不是 0 就生成位图、重新描绘全部项目
@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
end
[/pre][/fold]
for i in 1...$data_items.size
意思是从 1 开始检索,检索到items数据库的末尾,将数量>0的物品进行描绘
我们可以使用一种简单粗暴的方法,在脚本中手写数组,直接让物品强行按照我们所写的id号来进行先后排列::
[fold=强排][pre lang="ruby"]class Window_Item < Window_Selectable
#按定义区间排序的模块
def resort
for i in 0..@data.size
if @排序区间.include?(@data.id) and @data != nil
if @data.id != nil
@data_2.push(@data)
end
end
end
@排序区间 = []
end
# 做个别名,备用
alias :refresh_new :refresh
# 重新定义
def refresh
if self.contents != nil
self.contents.dispose
self.contents = nil
end
@data = []
# 添加宝物
for i in 1...$data_items.size
if $game_party.item_number(i) > 0 and $game_party.item_can_use?(i)
#判断物品是否可以使用↑
@data.push($data_items)
end
end
# 拆分重组————————————————————————————————————————————————————————
@data_2 = [] #临时区间
@排序区间 = [] #初始化
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# 注—:排序区间如果不是从小到大,要分开排序,否则无效!!!
# 区间,按自定义顺序安置 ■ #药水
@排序区间 = (90..110).to_a
resort
# 区间,按自定义顺序安置 ■ #食物
@排序区间 =[16,17,18,121,123,128,134,136,137,144,] +
(163..167).to_a
resort
# 区间,按自定义顺序安置 ■ #咒碑&道具&炸弹
@排序区间 =[12] + (80..89).to_a + (150..162).to_a +
(169..173).to_a
resort
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# 最后补充,防止忘记代入的物品,如已代入会在后面重复项检测中被剔除
for i in 0..@data.size
if @data != nil
@data_2.push(@data)
end
end
# 重组
@data = []
@data = @data_2.uniq # 去除重复项并代入
#—————————————————————————————————————————————————————————————————
# 在战斗中以外添加武器、防具——所以战斗中的不用管
unless $game_temp.in_battle
for i in 1...$data_weapons.size
if $game_party.weapon_number(i) > 0
@data.push($data_weapons)
end
end
for i in 1...$data_armors.size
if $game_party.armor_number(i) > 0
@data.push($data_armors)
end
end
end
# 如果项目数不是 0 就生成位图、重新描绘全部项目
@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
end
[/pre]
[/fold]
直接手写的方式简单粗暴,直接把要相邻放置的物品ID填写在一个个数组里即可,且顺序完全可控。脚本后文添加防漏代入,也能够避免强排过程中漏填物品导致背包中的物品消失。
而麻烦点也显而易见,那就是填入排列数组时,每一个物品都得手动添加,如果物品不是相邻的,那还得到数据库一个一个找ID号,然后一个一个填入。
后面有几种别的排列方法我没有实际落入脚本当中,不过可能也具有一定的可行性。
1、按照@data 中item的各种字段属性进行排序;可以是其中对象的 name 的首字母 (这个太粗暴了),name的字数(看起来很舒服,但逻辑上没啥关系)
2、按照item名称中的关键字进行排序;比如,如果物品的名称含有“宝石”,那么就将其排列在一起;含有“药水”,就将其排列在一起。(很方便,但是对物品的命名比较严格;毕竟同样是剑类武器,我可以叫它铜剑、铁剑,也可以叫它镇天、开天...)
3、按照item的描述中的关键词进行排序;比如,在描述的开头或结尾写上【药水】【宝石】【剑】【弓】...然后同上逻辑进行排列。
4、按照item的属性&属性防御进行排序;我新添加若干的【属性】,将序号>**的属性名字命名为【药水】【宝石】【剑】【弓】.....然后在对应处打勾就好了。排列时检索 该物品的属性中,序号>** 的属性中,哪个是打勾的,它就属于哪个类。然后依次同类合并排序
以上是本人对物品排序的理解和一些经验,欢迎大家讨论分享新的items排序方法和理念。 |
|