さて、今までRPGの作り方をやってきましたが、今回のLv5で最終回です。だんだんややこしくなって、講座向けの内容ではなくなってきたので、このへんでやめておきます。(追加することはあるかもしれませんが)
前回、簡単なシンボルエンカウントシステムを作りましたが、今回は、もうちょっと複雑なものを作ります。
ちょっとややこしくなりすぎて、講座向けではなくなってしまいましたが、一応説明しておきます。
◆仕様を決める
シンボルエンカウントシステムをどんな仕様にするか決めます。
・マップ上をモンスターがうろうろと歩き回っている
・モンスターの動きは、ランダム、主人公を追いかける、逃げるなど様々
・モンスターと接触すると戦闘発生
・倒されたモンスターは、消滅する
・消滅したモンスターも、一定時間経過すると復活
・マップに入る度に、また復活するたびにモンスターの種類や位置が変わる
・主人公のレベルが高くなると、低レベルモンスターは、出現しにくくなったり、逃げることが多くなる
・接触した時の向きで、先制攻撃や不意打ちがある
これらのことを実現しようと思うと、並列処理で動きをコントロールし、接触の判定も独自に行わなければなりません。多少複雑になりますが、順番に作っていきましょう。
◆モンスターを出現させる
最初に、モンスターをマップ上に出現させます。
Lv4のシステムでは、マップに入ったときにすでにモンスターが出現していましたが、それではモンスターの種類や出現位置を変えられませんし、またセーブして終了してしまうと、次にロードしてきた時、全部のモンスターが復活してしまいます。それでは困るので、出現していない状態から初めて、そのつど適切に判断して出現させていきます。
まず、コモンイベントに、エンカウント出現待ちを作ります。このコモンイベントを、各モンスターのイベントから並列処理で呼び出します。
▼コモンイベント エンカウント出現待ちの内容 その1
順番に説明します。
最初に、変数を初期化しています。Lv4でもやりましたが、配列変数に[]を代入して、配列変数として設定します。(nilの場合のみ初期化。値が入っている場合は何もしない)
$wait_timeは、待ち時間を記録する配列変数です。
$enemy_numberは、現在出現しているモンスターの数を記録する変数です。
$revival_countは、マップに入ってから、出現したモンスターの、のべ数を記録する変数です。
次に、出現するモンスターの最大数を決める処理をしています。
$enemy_number_maxという変数で条件分岐し、$enemy_number_maxが、nilの場合、つまりまだ値が設定されていない場合にのみ設定します。
以下の処理で、出現最大数を設定します。
$enemy_number_max = 0 # 出現最大数に0を代入して初期化
for event in $game_map.events.values # マップイベントのデータを読み込んでループ
if event.name[/encount/] # イベント名に"encount"という文字列が含まれれば
$enemy_number_max += 1 # 出現最大数に1加算
key = [@map_id,event.id,"A"] # keyに、このイベントのセルフスイッチAを設定
if $game_self_switches[key] == true # keyに設定したセルフスイッチがONなら
$enemy_number += 1 # 現在出現中のモンスター数に1加算
end
end
end
$enemy_number_max /= 2 # 出現最大数を2で割る
始めてみる人は、「for event in $game_map.events.values」の部分が良く分からないと思います。
「for 〜 end」は、繰り返し処理を行うループ構造で、一定の範囲だけ繰り返し処理を行うのに使います。
例えば、
for count in 3..5
p count
end
と書いたとします。この場合、3から5までの範囲で繰り消し処理を行い、変数countの値は、一巡目は3に、二順目は4に、三順目は5になります。
p count というのは、変数countの値を表示するという命令です。("p"は表示命令です)
ですから、このスクリプトを実行すると、3と表示され、次に4と表示され、5と表示されて終了します。
さて、では「for event in $game_map.events.values」は、どういう意味でしょうか? この場合、「event」は、値を受ける変数です。先の例で言うと「count」と同じ役割の変数です。
「$game_map.events.values」は、マップイベントのデータが入った変数です。ここに、現在居るマップのマップイベントのデータが入っています。
したがって、この「for 〜 end」は、「$game_map.events.values」のデータの範囲内でループします。
例えば、現在居るマップに、マップイベントが3つあるなら、一巡目はひとつ目のイベントのデータが「event」に読み込まれ、二順目は二つ目のイベントのデータが、三順目は三つ目のイベントのデータが読み込まれます。そして、読み込むデータがなくなったらループを終了します。
ここでは、「for 〜 end」の間に、「event.name」と「event.id」の2つのデータを使っています。(ただし、「event.name」は、標準の設定では読めないので、後でスクリプトを少し改造します)
次の条件分岐、
if event.name[/encount/]
$enemy_number_max += 1
この部分は、イベントの名前に"encount"という文字列が含まれるかどうかで条件分岐するものです。
このシステムでは、モンスターとそれ以外のイベントを区別するために、イベントの名前を使います。エンカウント用のモンスターイベントは、イベントの名前に"encount"と書いておきます。
この条件分岐は、イベントの名前に"encount"が含まれていれば、$enemy_number_maxに1加算するというものですので、これでマップイベントの中で、名前に"encount"が含まれるイベントの数をカウントすることが出来ます。
次の処理、
key = [@map_id,event.id,"A"]
if $game_self_switches[key] == true
$enemy_number += 1
end
この部分は、「event.id」のイベントのセルフスイッチAがONになってるかどうかで条件分岐し、なっているなら$enemy_numberに1加算するというものです。
これは、セーブしロードしてきた場合に備えての処理です。このシステムでは、モンスターが出現するとセルフスイッチAをONにするため、すでに出現しているモンスターのイベントのセルフスイッチAは、ONになっています。
その状態でセーブすると、ロードしてきた時も、セルフスイッチAはONのままですから、最初から出現している状態でゲームが再開されます。
しかし、変数$enemy_numberは、ゲームを終了すると値が失われ、ロードするとnilから始まりますので、実際に出現しているモンスター数と、カウント数にズレが生じます。
それを補正するために、セルフスイッチAがONになっているイベントの数を、$enemy_numberに入れて、数を合わせます。
▼コモンイベント エンカウント出現待ちの内容 その2
順番に説明します。
最初に、現在のプレイ時間を取得します。
次に、待機時間が設定されていないなら、待機時間を設定します。
if $wait_time[@event_id] == nil # 待機時間がnilなら
sec = 3+rand(8) # 変数secに3と乱数を足したものを代入
sec += Graphics.frame_count/Graphics.frame_rate # 現在のプレイ時間を加算
$wait_time[@event_id] = sec # 待機時間にsecを代入
end
これで、待機時間が、現在のプレイ時間+3+乱数(0-7)に設定されます。
次に、出現するかどうかの判定を行います。
ここでは、条件分岐が3つ重なっています。つまり、3つの条件が揃った時のみ、モンスターを出現させる処理をするわけです。
最初の条件「$wait_time[@event_id] <= @sec」は、待機時間が現在のプレイ時間以下になったら、というものです。つまり待機時間が切れたら、出現条件の一つを満たすわけです。
二つ目の条件「$enemy_number < $enemy_number_max」は、現在の出現数が最大出現数を下回っている場合は、というものです。モンスターの出現数が、最大出現数以上にならないようにするためです。
この条件には、条件を満たさなかった場合の処理もあり、その場合、再び待機時間を設定します。その処理は、下記のようなものです。
sec = 0 # 初期化
sec += $revival_count * 5 # 今までの出現のべ回数に5をかけて加算
sec += rand(15) # 乱数を加算
for i in 0..$game_party.actors.size-1 # パーティに居る主人公キャラの人数でループ
sec += $game_party.actors[i].level * 3 # 主人公キャラのレベルに3をかけて加算
end
if sec <= 5 # もしsecが5以下なら
sec = 5 # secを5に設定
end
sec += Graphics.frame_count/Graphics.frame_rate # 現在のプレイ時間を加算
$wait_time[@event_id] = sec # 待機時間に代入
「sec += $revival_count * 5」は、今までの出現数が多いほど、次の待機時間を長くするための処理です。あまりモンスターが多く出現してもプレイしにくいので、だんだんと出現率を下げるためにこうしています。
仮に、すでにモンスターが10回出現しているなら、10*5=50で、50秒出現が遅れることになります。
下記の処理、
for i in 0..$game_party.actors.size-1
sec += $game_party.actors[i].level * 3
end
これは、主人公キャラのレベルが高いほど、次の待機時間を長くするための処理です。
主人公が4人で全員レベル4なら、4*4*3=48で、48秒待機時間が長くなります。
これは、主人公のレベルが上がったら、弱いモンスターを出現しにくくするためにそうしています。
「if sec <= 5 sec = 5」この処理は、待機時間が余りにも短すぎると困るので、最低でも5秒以上にするため処理です。
三つ目の条件「$game_map.events[@event_id].x != $game_player.x or $game_map.events[@event_id].y != $game_player.y」は、主人公と座標が重なっていない場合は、というものです。
主人公キャラと重なって出現すると変なので、座標が違う場合のみ出現させます。
この条件には、条件を満たさなかった場合の処理もあり、その場合、再び待機時間を設定します。その処理は、下記のようなものです。
sec = Graphics.frame_count/Graphics.frame_rate + 3
$wait_time[@event_id] = sec
つまり、待機時間を3秒に設定します。
出現条件を満たしたら、出現させます。
▼コモンイベント エンカウント出現待ちの内容 その3
順番に説明します。
各種カウント($revival_countと$enemy_number)に加算します。
$wait_time[@event_id]に、0を代入して、待機時間を初期化します。
$game_map.events[@event_id].opacityを0にして、透明にします。
次に、現在のキャラグラフィックを、このイベントの1ページ目のキャラグラフィックと同じものに設定します。
$game_map.events[@event_id].character_name =
$game_map.events[@event_id].event.
pages[0].graphic.character_name
これは、3行に分かれていますが、実は長い1行のスクリプトです。つまり、こういうことです。
$game_map.events[@event_id].character_name = $game_map.events[@event_id].event.pages[0].graphic.character_name
「$game_map.events[@event_id].character_name」というのが、現在のキャラグラフィックで、それに1ページ目のグラフィックである「$game_map.events[@event_id].event.pages[0].graphic.character_name」を設定します。
「pages[0]」とありますが、これが1ページ目の指定です。0から始まりますので、1ページ目が2、2ページ目が1ということになります。
(ただし、「$game_map.events[@event_id].event.pages[0].graphic.character_name」は、標準の設定では読めないので、後でスクリプトを少し改造します)
次に、画面内で出現する場合は、効果音を鳴らします。
このイベントが、画面内に居るかどうかを調べる条件分岐の条件は、下記の2つです。
$game_map.events[@event_id].screen_x >= 16 and $game_map.events[@event_id].screen_x <= 624
$game_map.events[@event_id].screen_y >= 32 and $game_map.events[@event_id].screen_y <= 480
「screen_x」と「screen_y」は、画面座標です。画面上のどの位置にいるかを知ることが出来ます。
イベントが、画面の左上隅に居る場合は、画面座標は、x=16 y=32になります。
イベントが、画面の右下隅に居る場合は、画面座標は、x=624 y=480になります。
したがって、イベントの画面座標が、その範囲内にある場合、画面内で出現したと判断し、効果音を鳴らします。
▼コモンイベント エンカウント出現待ちの内容 その4
順番に説明します。
不透明度を上げる、で少しづつ不透明度を上げて、姿を現します。
その後、セルフスイッチをONにして、出現した時の処理をするページに切り替えます。
最後に、イベントの一番最後で、ウェイトを20フレームかけています。
このイベントは、多数のイベントから、常に呼び出され続けるものですから、ウェイトを多めにして負荷を減らしています。
◆スクリプトを変更する
先に書いたとおり、スクリプトを少し変更します。
標準の設定では取得できない、次の二つの情報を取得できるようにするためです。
event.name #イベントの名前
$game_map.events[@event_id].event.pages[0].graphic.character_name #イベントの1ページ目のキャラグラフィックのファイル名
まず、スクリプトエディタを開いて、「Game_Event」というスクリプトを開きます。
最初の方にいくつか追加します。図を見てください。
▼スクリプト「Game_Event」の内容
この図で言うと、15〜17行目の下記の部分、
attr_reader :name # 追加分
attr_reader :event # 追加分
attr_reader :pages # 追加分
そして、32行目の下記の部分です。
@name = @event.name # 追加分
これで、情報が取得できるようになります。
◆エンカウントイベントを設定する
さて、それでは、実際にエンカウント用のモンスターイベントを作ってみましょう。
全部で4ページになりますが、まず最初の3ページです。
▼エンカウントイベントの内容 1ページ目
最初のページは、ただモンスターのグラフィックを設定するだけです。このページは、出現しませんので、設定は何でもかまいません。
ただ、先に書いたとおり、出現時にこのページのモンスターグラフィックが使われますので、キャラグラフィックだけは、正しく設定しておく必要があります。
また、イベントの名前が、「encount スライム」になっていることに、注目してください。
先に書いたとおり、エンカウント用のイベントの名前には、「encount」という文字列が含まれている必要があります。エンカウント用のイベントか、通常のイベントかを区別していますので、間違えないようにしておきます。(ちなみに、encountの前や後に、他のことが書いてあっても大丈夫です)
▼エンカウントイベントの内容 2ページ目
2ページ目の設定で注目すべきは、「すり抜け」です。すり抜けになっていると、他のモンスターが上を素通りできます。
ツクールXPでは、キャラグラフィックが無しになっているイベントの上を、主人公キャラは素通りできます。しかし、他のイベントが移動ルートの設定などで移動する場合は、素通りできません。そこで、すり抜けにして、他のモンスターの通行の邪魔にならないようにしておきます。
また、「並列処理」になっており、コモンイベント「エンカウント出現待ち」を呼び出し続けます。
これで、「エンカウント出現待ち」で出現条件を満たせば、セルフスイッチAがONになって、出現します。
▼エンカウントイベントの内容 3ページ目
3ページ目には、まだ、イベント実行内容は設定していません。後で、設定します。
とりあえず、キャラグラフィックを設定することと、条件にセルフスイッチAを設定しておきます。
◆動作確認
この状態で、動作確認してみます。エンカウント用イベントをいくつかコピーして、実行してみてください。
うまくいけば、数秒で出現するはずです。出現数は、設置したエンカウント用イベント数の半分になるはずです。
◆モンスターを移動させる
セルフスイッチAがONになると、3ページ目に切り替わります。3ページ目は、モンスターを行動させるためのページです。
エンカウントイベントの3ページを下記のように設定します。
これも、並列処理でコモンイベントを呼び出し続けます。
このページの移動速度は、移動する際の一歩歩く速度に影響しますが、移動頻度は移動の間隔には影響しませんので注意してください。
▼エンカウントイベントの内容 3ページ目
順番に説明します。
最初にまず、配列変数を初期化しています。nilの場合空の配列を代入します。
次に、行動タイプを設定します。
$action_type[@event_id]は、行動のタイプを決める値を代入する変数です。
とりあえず、下記の8タイプを用意しました。
0=完全停止
1=ノーマル
2=好戦的
3=消極的
10=向き変えのみ
11=ランダムのみ
12=近づくのみ
13=逃げるのみ
次に行動速度を設定します。
$action_speed[@event_id]は、行動の間隔を決める値です。フレーム単位で設定します。
この値を40にすれば、40フレームごとに一歩移動します。
この値は、動き終わってから次に動くまでの時間ではなく、動き始めてから次に動くまでの時間です。したがって、一歩動くのに40フレームかかれば、次の一歩は動き終わった直後に始まります。
最後に、コモンイベント「エンカウント行動」を呼び出します。
◆コモンイベント「エンカウント行動」を作る
コモンイベントの「エンカウント行動」を作ります。
内容は下図の通り。
▼コモンイベント エンカウント行動の内容 その1
●変数の初期化
最初に、例によって変数を初期化しています。
$move_mode[@event_id]は、移動モードを設定する変数です。
移動モードは、下記の5つです。
0.停止
1.近づく
2.ランダム
3.逃げる
4.向き変えのみ
$wait_time[@event_id]は、出現待ちのときに待機時間を記録していた変数ですが、ここでは行動時間を記録するのに使います。
$move_judg[@event_id]は、移動モードを決定する際の判定用の変数です。
▼コモンイベント エンカウント行動の内容 その2
●移動モードの設定
移動モードの設定を行います。
$wait_time[@event_id]の値で条件分岐しています。
行動時間が残っているなら設定は行わず前回の設定のままもう一度移動し、行動時間が残っていないなら、改めて移動モードの設定を行う、そのための条件分岐です。
移動モードの設定では、まず$move_judg[@event_id]に乱数を代入し、1〜100の範囲の値を設定します。
それに、さらに主人公の合計レベルを加算します。これは、主人公のレベルが高いほど、モンスターが逃げる確率を高くするためです。
次に、$move_mode[@event_id]に、移動モードを代入して設定します。
この処理は、行動タイプにより設定方法が変わるため、$action_type[@event_id]の値によって条件分岐します。
例えば、行動タイプが0の場合、$move_judg[@event_id]の値に関わらず、必ず$move_mode[@event_id]に0が代入されます。なぜなら、行動イプの0は、完全停止で動かないからです。そのため、$move_mode[@event_id]には、0が代入され、移動モードは「0.停止」になるわけです。
行動タイプが1の場合は、$move_judg[@event_id]の値により、設定される移動モードが変わります。
$move_judg[@event_id]が、1〜25の場合、$move_mode[@event_id]は0に
$move_judg[@event_id]が、26〜50の場合、$move_mode[@event_id]は1に
$move_judg[@event_id]が、51〜75の場合、$move_mode[@event_id]は2に
$move_judg[@event_id]が、76以上の場合、$move_mode[@event_id]は3に
それぞれ設定されます。
つまり、行動タイプが1の場合は、4つの移動モードがほぼ均等の確率で選択されるわけです。ただし、主人公のレベルが$move_judg[@event_id]に加算されますので、レベルが上がるほど「3.逃げる」が選択される確率が高くなります。
移動モードが設定された後に、行動時間が設定されます。「$wait_time[@event_id] = 8+rand(8)」という処理です。これで、行動時間が8〜15の範囲で設定されます。
つまり、8〜15回、同じ移動モードで移動し、その後新たに移動モードが設定され、また8〜15回、同じモードで動く、ということを繰り返すことになります。
▼コモンイベント エンカウント行動の内容 その3
●向きの変更
モンスターの向きを変えます。
このシステムでは、まず向きを変えてから、一歩前進させて移動させます。
例えば、ランダムに移動させる場合、「ランダムに移動」で移動させるのではなく、「ランダムに方向転換」させた後に、「一歩前進」で移動させます。なぜ、わざわざ二つに分けているかといえば、向きを変えてから一歩前進する前に、主人公キャラとの接触判定をするからです。
▼コモンイベント エンカウント行動の内容 その4
●接触判定
接触判定をしますが、その前に、また変数の初期化をします。
何故ここでするかというと、この前の処理(向きの変更)で、ウェイトを使っているからです。並列処理の中にウェイトがあると、そこでセーブされる可能性があります。ゲームを終了した時には、変数が初期化されるので、初期化されてもいいように、ここで改めて今後使用する変数の初期化をしてやります。
$move_mode[@event_id]は、前にも使いました。移動モードを記録する変数です。
$my_x[@event_id]と$my_y[@event_id]は、エンカウント用イベントの座標を記録する変数です。
$touch_mode[@event_id]は、接触したかどうかを記録する変数です。
▼コモンイベント エンカウント行動の内容 その5
●接触判定のつづき
接触判定の処理です。まず、エンカウント用イベントの座標を$my_xと$my_yに代入します。
次に、エンカウント用イベントの向きによって分岐し、調べる座標を調整します。
「$game_map.events[@event_id].direction」というのが、向きが記録されている変数で、2なら下向き、4なら左向き、6なら右向き、8なら上向きです。
エンカウント用イベントの一歩前に、主人公キャラが居るかどうか調べたいので、調べる座標が一歩前になるように、座標に1を加算したり減算したりして調整します。
次に、調査する座標(エンカウント用イベントの一歩前)と主人公キャラの座標が同一かどうか調べて、同一なら$touch_mode[@event_id]に1を代入します。1は、接触したという意味です。
$touch_mode[@event_id]が1の場合、不意打ちの判定をします。不意打ちは、接触時の向きで判断します。
主人公キャラの横や後ろから接触した場合は不意打ちになります。
不意打ちの場合は、$encount_modeに1が代入され、不意打ちでない場合は、$encount_modeに0が代入されます。
不意打ち判定が終わったあと、セルフスイッチのBをONにし、イベント処理の中断でイベントを終了させます。
セルフスイッチのBは、エンカウント用イベントの4ページ目の条件に指定しておき、セルフスイッチのBがONになると、自動実行で戦闘が始まるようにしておきます。
▼コモンイベント エンカウント行動の内容 その6
●移動処理
接触しなかった場合、移動処理を行います。
まず、移動前に現在のエンカウント用イベントの座標を$my_xと$my_yに代入します。後で判定に使うためです。
次に、一歩前進させます。この移動ルートの設定には、「移動できない場合は無視」のチェックをつけておきます。
この一歩前進は、条件分岐の中に入っています。この条件は、「$move_mode[@event_id] >= 1 and $move_mode[@event_id] <= 3」です。
つまり、移動モードが1から3の間の場合は、一歩前進するというものです。移動モードが0の場合は、停止状態なので移動させないようにするためです。
▼コモンイベント エンカウント行動の内容 その7
●移動後の調整
前の処理でウェイトが入りましたので、例によって変数がnilになっていた場合の初期化をします。
ここで初期化するのは、$action_speedです。これは、エンカウント用イベントの方で設定される値ですが、これがnilになっていた場合は、仮に10という値を与えてやります。
次に、休止します。
「@wait_count = $action_speed[@event_id]」で、$action_speed[@event_id]の値分の、ウェイトがかかります。
ウェイトがかかったので、また、nilになっていた場合の初期化作業をします。
▼コモンイベント エンカウント行動の内容 その8
●移動後の調整のつづき
つっかえ判定をします。
移動前に記録した座標と、今の座標を比べ、変わっていなければ、障害物につっかえていると判断し、強制的に移動モードを「2.ランダム」に変えます。
ただし、移動モードが「0.停止」の場合と、「4.向き変えのみ」の場合は、座標は変わらないので、処理しません。
最後に、移動時間を1減らします。
「$wait_time[@event_id] -= 1」という処理です。一回行動するごとに、移動時間が減っていく仕組みです。
◆バトルの設定
エンカウント用イベントに4ページ目を作って、バトルの設定をします。
条件に、セルフスイッチのBを指定し、トリガーを自動実行にします。コモンイベント「エンカウント行動」の中で、プレイヤーと接触すると、セルフスイッチのBがONになるように設定しました。
このページは、自動実行で開始されますから、セルフスイッチのBがONになると即座にバトルが発生するわけです。
▼エンカウントイベントの内容 4ページ目
見ての通り、バトルの処理でバトルを発生させるだけのシンプルな処理です。
勝った場合、逃げた場合、負けた場合に、それぞれコモンイベントを呼び出すようにしてあります。
勝った場合は、コモンイベントを呼び出す前に、$wait_time[@event_id]に値を代入します。これは、次に復活する前の待機時間を算出するための基礎となる数値で、この値が小さいほど早く復活します。マイナスでもかまいません。
コモンイベントの内容を説明します。
▼コモンイベント バトルに勝利したときの内容 その1
最初に、モンスターを消します。効果音を鳴らし、徐々に透明にしていきます。
その後、ランダムに方向転換し、一歩前進を繰り返します。これは、消えた位置と次の出現位置を少しずらすためです。
▼コモンイベント バトルに勝利したときの内容 その2
変数を初期化します。
次に、$enemy_numberから1減算し、出現数を減らします。モンスターが1体消えたわけですから、その分減らすわけです。
次に、復活までの待機時間を設定します。
sec = $wait_time[@event_id] # エンカウント用イベントで設定した基本地を代入
sec += $revival_count * 5 # のべ出現回数に5をかけて加算
sec += rand(15) # 乱数を加算
for i in 0..$game_party.actors.size-1 # プレイヤーのレベルに3をかけて加算
sec += $game_party.actors[i].level * 3
end
if sec <= 5 # 待機時間が5以下なら5に設定
sec = 5
end
sec += Graphics.frame_count/Graphics.frame_rate # 現在のプレイ時間を加算
$wait_time[@event_id] = sec # 待機時間に代入
最後に、セルフスイッチAとBをOFFにして、出現待ちの状態に戻します。
▼コモンイベント バトルで逃げたときの内容
逃げた時は、移動モードを0にして、行動時間を2にします。これは、逃げた直後は少しモンスターを休止状態にするためです。
最後に、セルフスイッチBをOFFにして、行動ループに戻します。
負けた時は、ゲームオーバーにするだけです。
◆動作確認
動作確認してみます。エンカウント用イベントをいくつかコピーして、実行してみてください。
うまくいけば、モンスターから接触した時、戦闘が起きるはずです。
モンスターから接触するように、行動タイプを2や12にしておくとよいでしょう。
◆プレイヤーからの接触判定
今の状態では、モンスター側からは接触しますが、プレイヤー側からの接触はありません。
そこで、プレイヤー側からの接触を行うようにします。
スクリプトエディタを開いて「Game_Player」というスクリプトを選択してください。ここに、「● 接触イベントの起動判定」というのがあります。ここに下記のように追加します。
▼スクリプト 「Game_Player」
順に説明します。
# エンカウントシステムの接触判定 追加分 ここから
if event.x == x and event.y == y
# ジャンプ中以外で、起動判定が正面のイベントなら
if not event.jumping? and not event.over_trigger?
if event.name[/encount/] # 接触したイベントの名前に"encount"が含まれるなら
# 不意打ち判定
@e_d = $game_map.events[event.id].direction # 接触したイベントの向きを代入
@p_d = $game_player.direction # 主人公キャラの向きを代入
$encount_mode = 2 # とりあえず$encount_modeを2(主人公側の不意打ちの設定)に設定
if @e_d == 2 and @p_d == 8 # 接触したイベントと主人公が向き合っているなら
$encount_mode = 3 # $encount_modeを3(通常のエンカウント)に設定
end
if @e_d == 8 and @p_d == 2
$encount_mode = 3
end
if @e_d == 4 and @p_d == 6
$encount_mode = 3
end
if @e_d == 6 and @p_d == 4
$encount_mode = 3
end
key = [$game_map.map_id,event.id,"B"] # 接触したイベントのセルフスイッチBをkeyに設定
$game_self_switches[key] = true # セルフスイッチBをONに
$game_map.need_refresh = true # マップをリフレッシュ(リフレッシュしないとすぐに戦闘が起きないため)
end
end
end
# 追加分 ここまで
これで、プレイヤーから接触した場合も、戦闘が起きるようになります。
◆不意打ち
今まで、不意打ちの判定をして、「$encount_mode」に値を記録してきました。
$encount_modeが、1ならモンスター側の不意打ち、2ならプレイヤー側の不意打ちです。
これを、実際にバトルに反映させます。
まず、新しいステートを作るので、データベースを開いて、ステートタブをクリックしてください。
▼データベースの設定 ステート
上手のように、「不意打ち」というステートを設定しました。
ポイントは、「制約」の項目を「行動できない」にすること、そして解除条件で、0ターンで100%解除されるようにしておくことです。こうすれば、最初のターンだけ行動不能にすることができます。
次に、バトルイベントを編集します。データベースを開いて、トループタブをクリックしてください。
▼データベースの設定 トループ
上図のように設定します。バトルイベントの条件を「ターン0」にします。つまり、最初のターンにのみ発動するようにします。
あとは、コモンイベント「バトル0ターン目の処理」を呼び出すだけです。これは、全モンスター共通の処理なので、すべてのトループに同じように設定します。
コモンイベント「バトル0ターン目の処理」の内容は、下記の通りです。
▼コモンイベント バトル0ターン目の処理
このイベントは、シンプルですね。
$encount_modeの値で分岐して、ステートを変化させるだけです。
◆動作確認
これで、エンカウントシステムは、完成です。以下のようなことを確認してみてください。
・ちゃんとモンスターが出現するか
・プレイヤーからの接触判定は正常か
・モンスターからの接触判定は正常か
・横や後ろから接触した時の不意打ち判定は正常か
・勝利した時や逃げた時の処理は正常か
・消えたモンスターはちょんと復活するか
・セーブしてゲームを終了しロードしてきても正常に動作しているか
◆モンスターを配置する時の注意
モンスターをマップ上に配置する時、少し注意が必要です。
マップ上には、他のイベントもあります。マップ移動イベントや宝箱などです。これらのイベントがある場所にモンスターが近づいてこれると、トラブルの元になります。
例えば、出口にモンスターがつっかえて邪魔になるとか、宝箱を調べている間に、モンスターが集まってきて囲まれてしまうとか。
それもまた良いという考え方もありますが、他のイベントの周りからモンスターを排除したい場合は、グラフィックに何も指定しない透明なイベントを配置します。
イベントが移動ルートの設定などで、イベントが動く場合、他のイベントには重ならないという特性があります。これを利用して、透明なイベントでブロックするわけです。
これで、プレイヤーは通過できるが、モンスターは通過できない見えない壁ができますので、うまくモンスターの進入を防ぎましょう。