WOLF RPGエディター(ウディタ)[3.311]/演出・システム【サイトトップへ戻る】 ■画像の当たり判定について (更新:2024/04/11 画像の当たり判定について解説します。
ウディタに初めから用意されている戦闘システムの当たり判定については、別ページで紹介しています。 ■画像の当たり判定の基礎 画像同士の当たり判定の処理では、当たり判定を判定したい2つの画像の距離を測り、 その距離が一定の範囲内(画像が重なる範囲)である時に「当たった」と判断します。 例えば下図の場合は、敵キャラが発射した弾丸の中心と主人公の中心との距離を測り、 8ピクセル以内だった時に「当たった」と判断します。 四角形同士の当たり判定の場合は、「(Aの幅+Bの幅)÷2=両者の距離」の計算で両者の距離を算出し、 縦横ともに両者の中心からの距離が短い時(重なる距離の時)に「当たった」と判断します。 例えば「横40×縦30」と「横20×縦16」の2種類の四角形があった場合、 横の距離は「(40+20)÷2=30」、縦の距離は「(30+16)÷2=23」になるため、 両者の中心からの距離が「横30未満」「縦23未満」になった時に「当たった」と判断されます。 下図の場合は「横30未満」「縦23未満」になるため、この場合は「当たった」となります。 当たり判定の範囲が奇数の幅である場合は、中心からの上下左右の幅が同じになります。 例えば下図にように、当たり判定の範囲が「101×101」の場合は、 中心からの距離は上下左右全て「50」になります。 しかしマップ上のマス目のように偶数の幅である場合は、中心より右下にずれた位置が中心点になります。 ▼タイルサイズが[16×16]の場合 両者の距離を測る時に偶数幅と偶数幅、奇数幅と奇数幅で測る場合は、 「(Aの幅+Bの幅)÷2=両者の距離」で問題無く距離を測る事ができます。 しかし偶数幅と奇数幅で距離を測る場合は「(Aの幅+Bの幅)÷2=両者の距離」で計算すると、 上側と左側の当たり判定が1ピクセル足りない状態となり、正確な当たり判定を処理する事ができません。 例えば偶数幅[16]と奇数幅[1]を「(Aの幅+Bの幅)÷2=両者の距離」で計算すると、 「(16+1)÷2=8」の計算によって両者の距離は「8ピクセル」となり、 当たり判定の範囲は「中心から上下左右7ピクセル」になります。 正確な当たり判定を行う場合は、 「上側と左側は8ピクセル、下側と右側は7ピクセル」と言った処理が必要になりますが、 主人公に対する敵の弾丸の当たり判定を処理する場合は、 「上下左右8ピクセル(両者の距離を9ピクセルで処理)」で処理しても良いかと思います。 下記の設定例は「上側と左側は8ピクセル、下側と右側は7ピクセル」のイベント処理と、 「上下左右8ピクセル(両者の距離を9ピクセルで処理)」のイベント処理を比較したものです。 「上下左右8ピクセル(両者の距離を9ピクセルで処理)」の方がシンプルな処理となり、 コマンド処理数も若干少なくなります。
0.5マスずれた状態の敵キャラが弾丸を発射した場合、 「上側と左側は8ピクセル、下側と右側は7ピクセル」の場合は、 主人公の上側と左側しか弾丸が当たらず、右側と下側では弾丸がすり抜けてしまいます。 しかし「上下左右8ピクセル(両者の距離を9ピクセルで処理)」の場合は、 上下左右の全てで弾丸が当たるようになり、不自然な弾丸のすり抜けが無くなります。
キャラクター(主人公やマップイベント)にピクチャが当たっているかどうかを判断する時には、 イベントコマンド【変数操作+】の「キャラ」にある「画面X座標」「画面Y座標」を使って、 ピクチャの表示位置(中心)からの距離を測って、当たり判定を判定します。 「画面X座標」はキャラクターの左右中央の位置を取得し、 「画面Y座標」はキャラクターの足元の位置を取得します。 もしも足元にあるY位置をキャラクターの中心(マスの中央)へ移動させる場合は、 0.5マス分を減算してください。
▲トップへ戻る▲ ■マス座標の当たり判定(アクションRPGなどで使用) アクションRPGの戦闘システムの当たり判定では、 主人公がいるマスから0.5マス単位で1マスずつイベントIDを取得していき、 敵キャラのイベントIDが見つかったらダメージを与えると言った処理方法で当たり判定を判定します。 ▼0.5マス単位で調べていくイメージ 0.5マス単位で調べる方法の場合、タイルチップ(地形)の通行設定やタグIDを調べる事ができるので、 例えば壁の向こう側にいる敵キャラには攻撃が当たらないと言った処理を作る事もできます。 ピクチャの場合は…
壁に当たったら弾丸が消えると言った処理を作る事ができます。 マス座標はキャラクターが次のマスへ移動を開始した瞬間に移動先のマス座標になります。 そのため、見た目では当たっているのにダメージを受けない、 または見た目では当たっていないのにダメージを受けると言った現象が起こります。
同じマスに複数のマップイベントが重なっている状態で、そのマスのイベントIDを取得した場合は、 小さい方のイベントIDを取得します。 そのため、敵キャラと敵キャラではないマップイベントが同じマスに重なる事がある場合は、 敵キャラのイベントIDを小さいイベントIDにしておかないと、 敵キャラの当たり判定を処理する事ができません。
このマス座標の当たり判定の処理を応用して、敵キャラの監視システムを作る事もできます。 処理としては、並列実行で常に敵キャラの目の前の数マスに主人公が居ないかどうかを調べて、 主人公を見つけた場合は、「プレーヤー接近」で追いかけてきたり、遠距離攻撃を行ったりします。 ▲トップへ戻る▲ ■[角度][cos][sin]を使って斜めの距離を算出(円形の当たり判定) 斜めの距離を算出する時には、 イベントコマンド【変数操作】にある「角度」「cos」「sin」を使って処理します。 「角度」は両者の縦横の距離から算出します。 角度は「0.1度単位(360度=3600)」なので、下図の角度は「2066(206.6度)」になります。 ▼角度を出す処理の設定例
「cos」と「sin」は、指定した角度で直線「1000」の距離を進む時の縦横の増減値を算出します。 「cos」は横の増減量であり、中心から右側がプラス値、左側がマイナス値になります。 ▼角度(水色の数字)と「cos」「sin」の値 例えば角度「0」の場合は「cos=1000、sin=0」なので、 角度「0」で直線に1000ピクセル移動させる場合は「X+1000」「Y+0」になります。 角度「3150」の場合は「cos=707、sin=-707」なので、 角度「3150」で直線に1000ピクセル移動させる場合は「X+707」「Y−707」になります。 「角度」と「cos」か「sin」を組み合わせると、斜め方向の距離を算出する事ができます。 以下の設定は、両者の縦横の距離から角度を算出し、角度から「cos値」を出して、 両者との直線状の距離(斜めの距離)を出す時の設定です。 「cos=0」の場合は角度「900」か「2700」(横の距離ゼロ)であるため、 縦の距離をそのまま両者の距離にしています。
下図の両者の距離は「71ピクセル」になります。 斜めの距離を調べる処理を使うと、円形の当たり判定を調べる事ができます。 例えば下図の2つの円形の当たり判定を判断する場合、 四角形の当たり判定を使った時には「当たっている」と判断されますが、 斜めの距離を測る処理を使った時には「当たっていない」と判断されます。
このように円形同士の当たり判定を処理したい時には、斜めの距離を調べる処理が必要になります。 「角度」「cos」「sin」は処理が重くなるコマンドであるため、 「角度」「cos」「sin」を使った処理が多くなると、処理落ちが発生しやすくなります。 そのため、大量の円形同士の当たり判定を調べる時には、 まずは四角形の当たり判定で調べて、四角形の当たり判定で当たっているかどうかを調べた方が良いでしょう。 元々角度を調べるために両者の縦横の距離を算出しておく必要があるため、 その両者の縦横の距離の情報を使って、四角形の当たり判定を調べます。 四角形の当たり判定で「当たっている」と判断された場合は、 さらに斜めの距離を調べて実際に当たっているのかどうかを調べます。 こうする事で処理の軽減に繋がります。 ▼この場合は四角形の当たり判定で「当たっていない」と判断できるため、斜めの距離は調べません。 ▼YADO作品「ニナと会話」では、1フレームごとに大量の円形の当たり判定を行う必要があるため、 四角形の当たり判定を調べてから斜めの距離を調べる処理を採用しています。 四角形と円形との当たり判定の場合も、まずは四角形の当たり判定で当たっているかどうかを判断します。 四角形の当たり判定で「当たっている」と判断された場合で、 四角形の角と角の間に円形の中心がある場合は、そのまま「当たっている」と判断します。 四角形の角と角の間に円形の中心が無い場合は、円形の中心に最も近い四角形の角からの距離を算出し、 当たっているかどうかを判断します。 処理落ち対策として、弾丸などの小さな円形の場合は、中心点のみを当たり判定の対象にしたり、 ちょっと大きめの円形の場合は、円の内側に四角形やひし形で当たり判定の範囲を設定するなど、 斜めの距離を調べないで当たり判定にすると、処理落ちの軽減に繋がります。 ▼赤い部分を当たり判定の範囲とする。 ▲トップへ戻る▲ ■弾丸の表示について 弾丸の表示方法は、一応いくつかの設定候補がありますが、 実用的なのは「ピクチャで表示(1フレーム移動)」になります。
■弾丸の移動量に関して ピクチャで表示(1フレーム移動)で弾丸を移動する場合、 1フレームごとの移動量を増やすと、弾丸の移動速度が速くなります。 ▼移動量が異なる弾丸を同時に発射した場合 1フレームごとの移動量を16ピクセルや24ピクセルにすると、さらに弾丸の移動速度が速くなりますが、 しかしあまりに1回の移動量が多くなると、当たり判定の対象物を貫通してしまう可能性があります。 例えばタイルサイズ[16×16]の時に、弾丸を1フレームで24ピクセル移動させた場合、 下図のように壁のマスを貫通して移動してしまう可能性があります。 貫通を防ぐには、タイルサイズ以下で当たり判定を処理する必要があり、 1フレームで24ピクセル移動する場合は「1フレームにつき12ピクセル移動×2回処理」や、 0.5マス単位の場合は「1フレームにつき8ピクセル移動×3回処理」などで処理する必要があります。 ■指定した角度へ弾丸を飛ばしたい場合 ピクチャで表示(1フレーム移動)で弾丸を移動させる場合、 1フレームごとに弾丸(ピクチャ)の表示位置を「X+2、Y−1」などと増減して移動させます。 しかし単純に「X+2、Y−1」などで処理すると、長距離の攻撃では目標に当たらない事があります。 例えば下図の場合、「X+3、Y+1」と「X+2、Y+1」で弾丸を飛ばしていますが、 どちらの弾道も主人公がいるマスには通らないため、主人公がダメージを受ける事はありません。 より正確に目標へ向かって弾丸を飛ばしたい時には、両者の角度を調べた上で、 「cos値」「sin値」を使って弾丸を移動させると良いでしょう。 弾丸には弾丸1発ごとに「cos値」「sin値」「合計cos値」「合計sin値」を保存する変数を用意します。 そして1フレームごとに「合計cos値」には「cos値×3」、「合計sin値」には「sin値×3」をそれぞれ加算し、 「合計cos値」「合計sin値」が「1000以上」か「-1000以下」になったら、 「1000=1ピクセル」「-1000=-1ピクセル」で弾丸を移動させます。 弾丸を移動したら、「合計cos値」「合計sin値」は「余剰1000」で「-999〜999」になるようにします。 上図の場合、敵キャラから見て主人公は「角度=218」に居るため、「cos=928」「sin=371」になります。 敵キャラから弾丸が発射されると、以下のように弾丸の移動量を算出して、弾丸を主人公の方へ飛ばします。
▼処理結果(弾丸の弾道) 下記のマップイベントを設定すると、実際に「cos」「sin」を使った弾丸の移動処理を確認する事ができます。 複数体の敵キャラで動作確認したい場合は、下記の敵キャラを1体作成し、 マップイベントごとをコピー&貼り付けで増やしてください。 弾丸のピクチャ番号は「イベントID+100=ピクチャ番号」で設定しているので、 コピー&貼り付けで増やすだけで、自動的に敵キャラごとに異なるピクチャ番号が使用されます。 弾丸は敵キャラ1体につき1発のみで、弾丸が消えたら次の弾丸を発射します。 弾丸はゲーム画面の外に出るか、主人公に当たると消えます。 処理落ち対策として、ゲーム画面の外にいる敵キャラは弾丸を飛ばしません。 仮に飛ばしたとしてもゲーム画面の外なので、すぐに弾丸は消えてしまいます。
▼変数に関する補足
■アクションRPGの遠距離攻撃では弾丸の表示しない作品もある アクションRPGで銃の遠距離攻撃を行う時に、弾丸を表示しない作品も存在します。 ▼弾丸を表示しない場合の動作イメージ 弾丸を表示しないと、以下のようなメリット・デメリットがあります。
■エフェクトの「描画座標シフト(最終値)」は弾丸処理では使えない イベントコマンド【エフェクト】の「ピクチャ」には「描画座標シフト(最終値)」と言った設定があります。 この「描画座標シフト(最終値)」を使ってもピクチャを移動させる事ができますが、 しかしこの「描画座標シフト(最終値)」でピクチャを移動させてもゲーム画面上の表示位置が変わるだけであり、 イベントコマンド【変数操作+】の「ピクチャ」で取得できる「X座標」「Y座標」の値は変わらず、 当たり判定の処理には使えません。 ▲トップへ戻る▲ ■主人公の周りに障害物を検知する処理を設定(横アクション用) 横スクロールのアクションゲームやシューティングゲームなどで、 プレイヤーが操作する主人公をピクチャで表示する事がありますが、 ピクチャで表示した場合は、通行不能の障害物を検知する処理が必要になります。 基本的にはピクチャを表示している位置のタイルチップの通行設定やタグIDを読み取って、 障害物の有無(通行不能かどうか)を判定しますが、ピクチャの表示位置(画像の中心)で調べた場合、 下図にように主人公が障害物にめり込んでしまいます。 このような問題を防ぐには、主人公の周りに障害物を検知する処理を設定する必要があります。 下図の場合は、10箇所に障害物を検知するポイントを設定しています。 移動時は1ピクセルずつ移動させて、障害物があったら、それ以上は移動しないようにします。 ▼落下処理の場合 1フレームで3ピクセル移動させる場合は、 1ピクセルずつ障害物を調べていく処理を1フレームごとに3回実行させます。 障害物を検知するポイントの設定は、タイルサイズ[16×16]の場合は16ピクセル以内に1箇所、 0.5マス単位で処理する場合は8ピクセル以内に1箇所の設定が必要です。 ▼0.5マス単位で処理する場合は、隣りのポイントまでの距離を8ピクセル以内で設定 ポイントの設定が足りないと、下図のように障害物を貫通してしまいます。 障害物がマップイベントの場合は、タイルセットの当たり判定を処理する時に…
しかし0.5マス単位で通行設定を調べても、マップイベントの画像サイズが小さい場合や マップイベントが移動している場合は、主人公とマップイベントとの間に隙間ができてしまう事があります。 下図はマップイベントが左へ0.5マス移動し始めた瞬間の状態です。 移動し始めた瞬間に黄色の枠の部分が通行不能(マップイベントがいる)になるため、 この状態で主人公はこれ以上右へ移動する事ができません。 また通行設定はマップイベントを設置した1マス分のみの当たり判定になるため、 画像サイズが大きいマップイベントの場合は、マップイベントの画像と主人公が重なり合ってしまいます。 ▼上に乗った時 主人公の周囲のイベントIDを調べて、当たり判定を処理した場合も、上記と同じ仕様になります。 上記の仕様に問題がある場合は、通行設定やイベントIDで当たり判定を処理せず、 両者の距離から当たり判定を処理する方法で処理した方が良いでしょう。 ▲トップへ戻る▲ ■弾丸の先端が攻撃範囲に入ったら「当たった」とする 矢などの長細い弾丸画像を用意する際、弾丸の前方に透明な余白部分を設定し、 弾丸の先端が画像の中心になるようにすると、弾丸の先端部分が当たり判定の基点となり、 弾丸の先端部分が当たり判定の範囲内に入った瞬間に「当たった」となります。
なお、余白の幅を半分にすると、 「弾丸の中心が画像の中心」と「弾丸の先端が画像の中心」の中間くらいの位置が当たり判定の基点になります。 ▲トップへ戻る▲ ■ピクチャの角度で弾丸を表示(表示のガタつき軽減対策) 弾丸画像を設定したピクチャの「角度」を弾丸を飛ばす方向の角度に変える事で、 飛んでいく方向に合わせて弾丸画像の表示角度を変える事ができます。 ▼角度「150」(15.0度)を設定した場合 「角度=0」は右向きになるため、弾丸画像も右向きで用意してください。 なお、90度角以外で表示する場合、画像の表示にガタつきが出る事があります。 もしも画像のガタつきが気になるようでしたら、弾丸の画像を10倍のサイズで作成し、 ピクチャで表示する時には「拡大率=10%」で表示すると、角度を変えた時のガタつきが軽減されます。
▲トップへ戻る▲ ◎関連ページ ◆戦闘システムの当たり判定(命中率・回避率)について |