RGSS2備忘録その1 壁の上を歩行可能にするスクリプト
今日からRGSS2シリーズをやっていきます。ヤッタネ(^▽^)
ちなみにRGSS2というのはRPGツクールVXでの話しとなります。
XPではないのでお間違えのなく。
で、第1回目は壁グラフィック上を通行可能にする方法であります。
壁グラフィックはダンジョン生成コマンドで使われる壁グラフィックのタイル群です。
通行可能にするのはもちろん、視覚的に水平に見える方です。
垂直に見える壁は、そのまま通行不可のまんまとします。
これ以降、通行可能にする壁グラフィックのことを水平壁と呼ぶことにします。( ・`ω・´)
通常、通行可能、不可能を設定する場合は、ツクール上で通行設定というアイコンを
クリックするか、メニューから選択し、タイル別に○か×を選んでやります。
しかし、そうやると地面と水平壁の間を自由に行き来できるようになってしまいます。
それを回避するために、通行不可のイベントを境目に配置するという方法でも
できなくはないですが入り組んだ一マス分の通路とかは、作れません。(´;ω;`)ウッ
そこで、タイルごとの通行属性を改ざんすることで、そこの問題をうまく回避
しようと思います。
今回は、かなり長くなりそうなのでSupponはここいらで、
お茶を一杯いただこうかとおもいます。
ズズズズズズ←お茶をすする音
(*^▽^)ノアイッ ごちそうさまでした。
では説明にもどります。( ・`ω・´)
まず、タイルグラフィックそれぞれには、個々にIDと通行属性のデータ
が割り当てられています。
それぞれのタイルのIDはトリアコンタンさんという方のホームページに
エクセルのデータとして公開されています。
こちらです→Delusional Field
そちらを拝見すると一目瞭然です。(^▽^)ヤッタネ
一番左上の水平壁のIDは5888はになります。
次に通行属性のデータについてですが、通行可能、不可能はビットでの比較で
行われます。ヘルプやスクリプトにはなぜか、わかりにくい16進数で表記されていますが、
2進数表記であらわすと、わかりやすいです。
↓画像にまとめました。
1の位が0なら歩行可能、1なら歩行不可
2の位が0なら小型船通行可能、1なら通行不可という感じです。
普通の何もない歩行可能な地面なら00000110(0x06)になります。
このような通行属性データがそれぞれのタイルに割り当てられています。
一番左上の水平壁のIDは5888で、その隣は5936になっているのがわかると思います。
なぜこうなっているかというと、オートタイルの組み合わせで、一種類の水平壁は
46通りの組み合わせがあるからなのです。
5936 - 5888 = 48 なので、48通りあるのかと思うかもしれませんが、おそらく残り2つは
使われてないと思います。おそらく48っていうのが 16 * 3 なので、ちょうどキリがいい
数字だから、48ずつIDを割り当ててるんだと思います。
で、どのような組み合わせがあるのかというと、このようになります。多分これで全部です。
わかりやすいように境界を見やすくしました。
この画像に表示されてる番号は、その種のタイルIDの開始番号を差し引いた、それぞれのタイルのIDです。したがって、番号0のタイルのIDは5888です。
続いて、これら46通りの通行属性をつくってみます。
とはいっても、46通りすべて違うデータにする必要はありません。
肝心なのは、4方向で通行可能なのはどの方向かということです。
なので、0番目から15番目までは4方向とも通行可能なので、同じデータでいいっていう
ことがわかるとおもいます。
ここでどのように通行属性を割り当てるかというと、
先ほどの2進数の表記で6の位が空いているのがわかります。なので、水平壁は
とりあえず、この6の位を1とします。そして下4桁で、上下左右の通行可能・不可能を
表したいとおもいます。
とするとこうなります。
だいぶ疲れてきましたが、こんなことでへこたれるSupponではありません( ・`ω・´)
でも、ここで一息いれようと思います。( ^ω^)
ズズズズズ ←ココアをすする音
(*^▽^)ノアイッ ご馳走様でした。
ではつづけます( ・`ω・´)
スクリプト上でこれら46通りのタイルに通行属性を割り当てます。
class Game_Map
#--------------------------------------------------------------------------
# ● セットアップ
# map_id : マップ ID
#--------------------------------------------------------------------------
def setup(map_id)
@map_id = map_id
@map = load_data(sprintf("Data/Map%03d.rvdata", @map_id))
@display_x = 0
@display_y = 0
@passages = $data_system.passages
for m in 0..2
for k in 0..7
j = 5888 + 48 * k + 768 * m
for i in 0..47
if i < 16
@passages[i + j] = 0x06
elsif 16 <= i and i <= 19
@passages[i + j] = 0x21
elsif 20 <= i and i <= 23
@passages[i + j] = 0x22
elsif 24 <= i and i <= 27
@passages[i + j] = 0x24
elsif 28 <= i and i <= 31
@passages[i + j] = 0x28
elsif i == 32
@passages[i + j] = 0x25
elsif i == 33
@passages[i + j] = 0x2a
elsif i == 34 or i == 35
@passages[i + j] = 0x23
elsif i == 36 or i == 37
@passages[i + j] = 0x26
elsif i == 38 or i == 39
@passages[i + j] = 0x2c
elsif i == 40 or i == 41
@passages[i + j] = 0x29
elsif i == 42
@passages[i + j] = 0x27
elsif i == 43
@passages[i + j] = 0x2b
elsif i == 44
@passages[i + j] = 0x2d
elsif i == 45
@passages[i + j] = 0x2e
elsif i >= 46
@passages[i + j] = 0x2f
end
end
end
end
referesh_vehicles
setup_events
setup_scroll
setup_parallax
@need_refresh = false
end
end
こんな感じになります。(´・ω・`)
新しい通行属性データは、@passagesというインスタンス変数に格納します。
つぎに、Game_CharactorクラスとGame_Playerクラスで
新しい通行判定メソッドを設定してやります。
今回はpassable2?(x, y, self_x, self_y, flag = 0x01)というメソッド
をつくります。
x, yは移動先のタイル、self_x, self_yは今自分が立っている場所のタイルの座標です。
class Game_Charactor
def map_passable?(x, y)
return $game_map.passable2?(x, y, @x, @y)
end
end
class Game_Player
def map_passable?(x, y)
case @vehicle_type
when 0 # 小型船
return $game_map.boat_passable?(x, y)
when 1 # 大型船
return $game_map.ship_passable?(x, y)
when 2 # 飛行船
return true
else # 徒歩
return $game_map.passable2?(x, y, @x, @y)
end
end
end
最後に、実際の判定処理の改造です。
class Game_Map
def passable2?(x, y, self_x, self_y, flag = 0x01)
for event in events_xy(x, y) # 座標が一致するイベントを調べる
next if event.tile_id == 0 # グラフィックがタイルではない
next if event.priority_type > 0 # [通常キャラの下] ではない
next if event.through # すり抜け状態
pass = @passages[event.tile_id] # 通行属性を取得
next if pass & 0x10 == 0x10 # [☆] : 通行に影響しない
return true if pass & flag == 0x00 # [○] : 通行可
return false if pass & flag == flag # [×] : 通行不可
end
for i in [2, 1, 0] # レイヤーの上から順に調べる
tile_id = @map.data[x, y, i] # タイル ID を取得
return false if tile_id == nil # タイル ID 取得失敗 : 通行不可
pass = @passages[tile_id] # 通行属性を取得
self_pass = @passages[@map.data[self_x, self_y, 0]]
if i == 0 and flag == 0x01
if self_pass & 0x20 == 0x20 #★ 今たっている場所の水平壁判定
if x > self_x #右を向いている
return false if self_pass & 0x04 == 0x04
elsif x < self_x #左を向いている
return false if self_pass & 0x01 == 0x01
elsif y > self_y #下を向いている
return false if self_pass & 0x08 == 0x08
elsif y < self_y #上を向いている
return false if self_pass & 0x02 == 0x02
end
end
if pass & 0x20 == 0x20 #★ 移動先の水平壁判定
if x > self_x #右を向いている
return false if pass & 0x01 == 0x01
elsif x < self_x #左を向いている
return false if pass & 0x04 == 0x04
elsif y > self_y #下を向いている
return false if pass & 0x02 == 0x02
elsif y < self_y #上を向いている
return false if pass & 0x08 == 0x08
end
return true
end
end
next if pass & 0x10 == 0x10 # [☆] : 通行に影響しない
return true if pass & flag == 0x00 # [○] : 通行可
return false if pass & flag == flag # [×] : 通行不可
end
return false # 通行不可
end
end
となります。
かなり長いですが、これはSupponの構文の作り方がへたくそだからです。
うまい人だったら、もっと短い文でまとめられるのではないかと思います。
これで、このような立体的なマップもつくれるようになったのではないでしょうか。

では、今日はこのへんで(^▽^)ノシ