お返事

 2020-02-05
お返事は続きから。

> RGSS2講座を読みながら新しいシーンづくりに挑戦中ですが行き詰ってしまうました。わかる範囲で構いませんのでアドバイス頂けたら助かります。

Window_Base#draw_actor_face が何をしているかはご存じでしょうか?
定義を見ると draw_actor_face(actor, x, y, size = 96) となっており、
Game_Actor オブジェクトを渡すと座標(x,y)に顔グラを描画する処理となっています。
つまり、改行とは y 座標の変化なので第三引数を変更すれば良いです。

4人までのy座標は同じで、x座標は0~3の範囲で変化させたいので、
i = 0...MAX のとき、Z順で並べる漸化式が

Xi = i % COLUMN_MAX * WIDTH
Yi = i / COLUMN_MAX * HEIGHT
となります。И順なら逆ですね。
% は、剰余といって割り算の余りを出す計算です。

for actor in $game_party.members
x = actor.index % 4 * 96 + 2
y = actor.index / 4 * 96 + 2
draw_actor_face(actor, x, y, 92)
end

この場合、actor.index は非常に無駄の多い処理ですので、

$game_party.members.each_with_index do |actor,index|
x = index % 4 * 96 + 2
y = index / 4 * 96 + 2
draw_actor_face(actor, x, y, 92)
end
のようにするのが良いかと思います。

これで、表示位置はクリアできると思います。


次にスクロールについて。
スクロール機能は Window_Selectable で実装されていますが、その根幹となる機能は Window クラスにあります。
ウィンドウは、外観と内容で構成されています。
VX では、外観となるウィンドウから四方 -16px の位置が内容を表示する領域と決められています。
この領域から内容となる Bitmap オブジェクトがはみ出すとスクロール矢印が表示されます。
ですから、contents にウィンドウ内容の表示領域より大きな画像を渡せばいいわけです。

そして、ウィンドウ内容は ox,oy プロパティを変更することで表示位置を変更できます。
通常の座標が画面の左上を原点(0,0)とするのに対し、これは、原点をどこにするかを設定します。
oy=16とすれば、内容の原点が(0,16)になり、内容は上にずれます。
chl4RfWypI.png
ウィンドウ内容は、ウィンドウのサイズに合わせて自動で作成されています。
create_contents を再定義して、必要なサイズの Bitmap オブジェクトを作成してください。

def create_contents
self.contents.dispose
self.contents = Bitmap.new(
width - 32, 96 + $game_party.members.size / 4 * 96)
end

スクロールは、update を再定義して、入力に合わせて oy を変更してください。

def update
super
if Input.repeat?(Input::DOWN)
self.oy += 96
self.oy = 0 if self.contents.height - 96 < self.oy
elsif Input.repeat?(Input::UP)
self.oy -= 96
self.oy = self.contents.height - 96 if self.oy < 0
end
end


説明していたらものすごく長くなることに気づいてしまったので動作サンプルを用意しました。
スクロール処理など大事なところを端折ってしまいましたが、なんとか解読してください。

class Window_Party < Window_Base

def initialize
super(0, 0, 544, 416)
refresh
end

def create_contents
self.contents.dispose
self.contents = Bitmap.new(contents_width, contents_height)
end

def refresh
self.contents.clear
members.each_with_index do |actor,index|
x = index % col_max * item_width
y = index / col_max * item_height
draw_item(actor, x, y)
end
end

def update
super
# 内容の縦幅が表示領域の縦幅より大きい場合のみスクロール
if self.contents.height > contents_view_height
if Input.repeat?(Input::DOWN) # 下が押されている
self.oy += item_height
self.oy = 0 if self.contents.height - item_height < self.oy
elsif Input.repeat?(Input::UP) # 上が押されている
self.oy -= item_height
self.oy = self.contents.height - item_height if self.oy < 0
end
end
end

# 各アクターの描画
def draw_item(actor, x, y)
draw_actor_face(actor, x+item_padding_x, y+item_padding_y, face_size)
end

# 描画するアクターの配列
def members
# デフォルトではパーティは4人固定なので代用
@members ||= [*1...$data_actors.size].map {|i| $game_actors[i] }
# @members ||= $game_party.members
end

# 横に並べる数
def col_max
4
end

# ウィンドウ内容の表示領域 (このサイズは仕様で決まっている)
def contents_view_width
self.width - 32
end
def contents_view_height
self.height - 32
end

# ウィンドウ内容のサイズ (これが表示領域より大きいとスクロール)
def contents_width
contents_view_width
end
def contents_height
(members.size / col_max.to_f).ceil * item_height
end

# 1アクターの描画領域
def item_width
contents_width / col_max
end
def item_height
96
end

# 顔グラの大きさ
def face_size
92
end

# アクター描画領域に対する顔グラの余白
def item_padding_x
(item_width - face_size) / 2
end
def item_padding_y
(item_height - face_size) / 2
end

end
SS2002054443111.png
動作確認だけですので、シーンクラスは作成していません。
シーン内で update を呼び出すだけなので、問題ないと思います。

Window_Selectable は、カーソル使用を前提に作られているので、処理方法が異なりますが参考にしてみてください。
サンプルでは、Z順で1アクター毎のスクロールにしていますが、И順やページ毎のスクロールに改変してみると理解が深まるかもです。


[追記]
Window_Status をベースにというのを見落としてました。
ベースにというのが何をさしているのかわからないですが、Window_Status はアクター1人を対象としたウィンドウなのでパーティ全体を表示するためのウィンドウとしては不適切かと思います。
継承ではなく、定義の参考にしているのでしたらアクターの情報の描画が短くまとまっているので参考になるかもしれないですね。
コメント




 

 ※ コメント内にURLを含めるには、バッククォート(`)をURLの直前に付け加えてください。


管理人のみ閲覧許可 [?]

トラックバック
トラックバックURL:
http://cacaosoft.blog42.fc2.com/tb.php/802-4d31de81
≪ トップページ ≫
カレンダー
04 << 2020/05 >> 06
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31 - - - - - -

カテゴリー
最近の記事
最近のコメント
タグクラウド

リンク