■はじめに
このページの目的は?→整理のために記載
完全というわけではないが、現状実装している中で最善の処理になっている。
参考文献
→■こちら■
(というかパターン分けは、全体的にここのを使った)
完璧にやるなら天井など全部やるのが良いが、かなり簡略化出来るので、必要なものだけ取り出した話となる。
(残った課題は恐らく境界値の誤差問題も絡むので、さらなる条件分岐が必要になる)
■前提
・坂道は45度を想定
22.5度(2マスで1ます上昇)でも同じような処理で行けると思われる。
y=f(x)が処理出来れば良く、各処理はf(x)の内容によらない
・いくつかのパターンは無視する
坂の裏側やキャラが入り込めない地形パターンについては無視。
条件分岐増加で対処出来るが、あまりやるメリットがない。
・移動速度は1ます分を超えない
越えること前提だと、線分を見る、タイルサイズ単位で順番にズラしてチェックしていく
などやることがかなり多くなる
今回の話題の本質では無いので省略。
・凡例
凡例 |
E:空白
B:ブロック
S↑、S↓:→方向に移動したとき、上がるか下がるかのスロープ(坂)
左右方向は実はどっちでも良くて、「今登っている」か「下っているか」が重要
左右で分岐してそれぞれ処理を書いても良い。ただし、同じ事を書く羽目になる。
・座標系
一般的な座標系とする |
格子座標 |
とある点p(x,y)を含む格子座標PはP(x/W,y/W)cとなる(つまりXc=x/W,Yc=y/W)。
移動量/位置座標が小数点を含む場合、境界の切り捨てなどで怪しくなる。
まだ未解明の部分も有るので、今回は境界については省略。
・坂の高さ⊿y
⊿y=f(⊿x) |
■概要、結論
坂道の処理のポイントだけ書くと:・「現在乗っているタイル」と「横移動量Vx」を見て、進行方向(まっすぐ、登り、下り)でまず3つに分ける
・3つそれぞれで、目の前、1マス下、1ます上から調べていく。必要ならその上下も調べる。
といったところ。
ポイントとしては:
・まず全パターン洗い出して網羅する
・通常の地形判定で済むもの、考えなくて良いパターン、同じ処理で事実上処理出来るものをまとめる、あるいは除いていく
・基本的に網羅→分岐で整理していく
といったところ。
完璧ではないと言ったとおり、課題については最後の方で述べる
■基本地形判定
坂道に入る前に、タイル形式マップの地形判定について軽く述べる。
コレ単体でもかなり厄介だが、坂道に比べれば情報はある。
横移動時の接触チェック=格子座標上のブロックタイルを調べる |
どうしても横から調べるか縦から調べるかの2択になる。
→🦐は横スクロールACTは横移動が多いので横を先にやっている。
図に有るとおりx0→x1に移動したとして、上端y0からタイルサイズ(W)ずつチェックしていき、ブロックタイル(B)のタイルがないか判定する。
押し戻した位置 |
図の場合「左から右へ移動してタイルに左から接触」したので、位置x'は左端からキャラクタの横幅(Cw)だけ離す。
移動量(Vx)は0にでもしておく。
この押し戻しが曖昧だとガクガク震えたりする
次に「縦と横どちらからやるか」問題:
横からやるか縦からやるか |
a:横スクロールだとX先の方が何かとそれっぽくなる
b:Y先の場合、崖から落ち辛いメリットと、天井にひっかかるデメリットがある。
移動量が下向きならb、上向きならa…という方法でも良い
c:移動量が大きい方を先にチェック
カスり当てでいちいち止められないので気持ちよくなる可能性あり
d:キャラクタの横幅縦幅で判断
これはやったこと無いので効果不明
図の下側に書いたが、逆に壁に囲まれたときもどっちが先かで微妙に話が変わる
(接触時に摩擦力が働く、バウンドするなど厳密にやる場合は判定が必須)
これ以降、この通常地形判定を行っている部分は「☆」で示す。
■坂道判定
まず要素を考えていく。★分岐要素
・セルの境界を越えたかどうか
境界を越えたかどうか |
つまり、図のnoの場合は特に考える必要はない。
現在がスロープなら⊿y=f(⊿x)、それ以外なら地面、空中での移動処理をすればいい(通常地形判定☆)
というわけで、「セルを越えた時の話」のみする。
・空中か、ジャンプしたか、地面を歩いているか
移動前の接地の有無、Y軸移動量(Vy>0 )をについて考える必要がある。→直前が空中なら、位置によって判定する
移動後、地面より下なら上にせり上げる。
これは全体で共通なので、特別な処理は不要。通常地形判定☆でOK。
→移動前に設置。移動後も地面の中になった
これはそのまま地上に押し上げればいい。通常地形判定☆に当たる。
<0 p="">→移動前に接地していたが、次の位置で浮いていたらどうするのか?(落下速度Vy>=0)0>
<0 p="">ここは好みで処理を考える必要がある:
1.「地面から浮いたら、全てジャンプ扱いにする」
(ただし、これは下り坂でぴょんぴょんしてしまうのであまりよくないが、スライディングですっ飛ぶというのもアリはアリ)
2.「特定の地形パターン(山形スロープ)のみ空中にする」
3.「ジャンプしない限り、直前設置なら接地」
など色々やり方がある。
今回は「ジャンプしない限り接地」とした。
→直前に接地&移動後空中&Y軸移動量が負(Vy<0 u="">0>0>
<0 p=""><0 p=""> これも地味に重要で、ちゃんとしないと坂道でジャンプ出来なくなる。
ただし、そういう操作性にしたいならやっていいし、これも好み。
(結局好みの部分があるので、これが実装方法が多様化してしまうのが、あまり坂道処理情報の無い原因と思われる)0>0>
<0 p=""><0 p="">今回は「Vy<0 span="">」ものとした。
0>0>0>
<0 p=""><0 p="">
0>0>
・現在水平か、登っているか、下っているか
さて、「セルを越える」「接地」のみとなったので、後は現状によるパターン分け現在の状況は3パターン |
Slopeなし。隣の状況で変わるので、水平、またはその下をチェックすればいい
登り
登っているところ(キャラクターの左右は関係無し。右移動+右上がり坂=登り。左移動+左上がり坂=登り)
図を見ると分かる通り、水平かその上を見れば良い。
下り
下っているところ(右移動+左上がり坂、左移動+右上がり坂)
これも図を見ると分かる通り、水平か下を見れば良い。
★X軸判定処理
今回はX軸判定をまずやる。・現在非スロープだった→水平移動先がブロックならもどす。
それ以外(スロープ含む)だったらそのまま移動させる
・現在登りスロープ→「一つ上」を調べる。ブロックなら押し戻す(真横は不要)
・現在下りスロープ→水平移動先なら戻す
(一つ下は乗り上げる可能性あるのでチェック不要
★各パターンとその実装方法
・セルを越えた時のみどう処理するか判断する(越えないときは考えなくて良い)・接地のみ(今回の条件により、直前接地状態のときのみ考えれば良い)
・水平か、登りか、下りか(これは全部必要)
以上より、坂道判定は全パターンを描くと次のようになる(参考サイトのものを整理)
場合分け(ほぼ)全パターン |
まず要らないものを除く。
あり得ないパターンについては見たとおり。一応適宜解説する。
①:通常判定(☆)で十分な処理(空中へ出る)
ブロックから空中に出たとき、接地にこだわる必要は無い。通常判定(☆)でOK
☆:下にブロックがある場合
移動した先にブロックがあるなら、その上に載る…といった、通常判定(☆)で良い☆※1:ブロックに衝突
X軸は先に処理しているので、既に手前までしか動かない。よって
コレにあるとおり、現在の地形3パターンによって、見る位置の情報が変わる。
水平、下り:真横を見る
登り:登った先(1マス上)を見る
次に各パターンについて説明
②水平で移動した先にあるスロープに接地する
水平にスロープがある |
2:スロープセルなので、地面判定をする
3:もし埋まっていれば表面へ押し出す。
空中でも、「直前が接地していれ&次もVy>=0なら接地」条件により、必ず接地とする
スロープから別のスロープへ |
ただし、登りの場合はまず↑をチェックするので(後述)、あとは通常処理(☆)に任せることにはなる。
つまり移動前がどのセルでも、まず水平位置をチェック。
スロープなら着地判定をする。
③移動した先が空白(E)
その下にスロープがある |
もしその上にブロックがある場合など、頭をぶつけたかのチェックはX軸基本地形判定☆で既にやっているので、問題無いとする
1個下がったところにスロープ |
2.E(空間)なので下も調べる
3.スロープがあった。一端その下端でチェック※A
4.「直前が接地なら次も接地」条件に基づき、表面に押し上げる。Vy=0にする。
※A
これは「空中のまま当たり判定をする」という方法でも良い。
ただしそれは「空中なら必ずジャンプ状態にする」という条件でのみ重要となる。
今回は「直前接地しているなら次も接地」条件があるので、意味は無い。
なので、一端地面に埋まっている位置を基準とした(3)
④チェック箇所がブロック
水平で見たらブロックだった |
1.水平に見る
2.ブロックである。ただし、現在(1)スロープなので、ブロックの↑も調べる
3.スロープだった。一端その下端として地面位置を計算
4.地面に押し上げる
水平にチェックしたらスロープだった |
1.水平を見る
2.スロープだった
3,4.スロープブロックの下端をターゲットにする
5.地面に押し上げる
一応、一つ下がブロックの場合の処理を兼ねているので、これはこれでいいと思う。
★具体的な分岐
出そろったので、実際の条件分岐を見る。全分岐をやる必要はない。
境界問題など、数学的な問題の方が重要
水平始動
水平始動 |
a2:逆向きでも別に考え方は同じ
a3:移動先が空白
a31:その下も空白→☆
a32:そのしたがブロック→☆
a33,a34:下がスロープなら着地させてしまう。
a4:水平の先がブロック→先に水平移動チェックしていてひっかかっているので、この処理は不要(☆
登り始動
「まず」一つ上をチェックb1:空白なら通常処理。地面に必ず着地させるならそう処理してもいいが、別に気にならないと判断した。
b2:ブロックなら横軸判定で止まってるので考えなくていい(☆)
b3:逆向きスロープ。止めるというてもあるが、普通にスロープ処理でも良いと判断した。
これは好みの問題。
そういう配置を一切しない前提となる。
b4:同じスロープ:接地させる
上記より、上をチェックすればその下は別になんでもいいということになったので、上だけ見るようにした。
下り始動
下りの時はまず下を調べる。c1:下りスロープなら、接地させる
c2:逆向きでも、接地させちゃう(そういう配置は無い前提)
右側に妙な配置を載せているが、ないものとして対処している。
c3:下がブロックだった場合、その上も調べる
c31:空白だった→接地でも通常処理(☆)でも良い
c32,c34:スロープだった→そのスロープに接地させる
c33:ブロックだった→あまりこういう配置はさせない方がいいが、ブロックなら止めておく
省略しているが、下が空白(E)だった場合は通常処理(☆)で良い
■今後の課題
これも最善ではあるが完璧ではない。×タイルサイズを越える速度での判定が怪しい
これは前提で述べたとおり。特に言及しない×高速で移動するとガクガクする
常に接地しているため、境界問題がモロに出る。丁度格子の境界にある場合、坂の中にあるブロックで位置修正している場合がある(瞬間的にめり込んでいる)
結局どっちに寄せれば良いかの分岐が必要になる。
まだ研究中なので省略。
×坂道移動速度を考慮していない
実装時の問題だが、Vx/Vyが坂道に影響されないため、一見√2倍の速度で動いているようにみえる。ちゃんとやるなら加算値を(Vx/√2,Vy/√2)とすべきだが、今回は省略した。
(ちなみに速度ベクトル自体を変えちゃうとおかしくなるので、「座標加算時のみ」という点に注意)
0 件のコメント:
コメントを投稿