AIを作成していて、リーチは十分なはずなのにコンボがスカる、と言ったことを経験された方は多いと思います。
かく言う僕もそうで、それをなんとかして防ぎたいと思ったので色々検証したので
せっかくだから誰かの役に立つかもしれないと思い、その結果をここにまとめてみようと思います。
間違ったことを書いているかもしれないので誰か突っ込んでくれると有難いです。
結論から先に言うと、現在自分は以下のような記述で対応しています。
・まずAIの上のほうに下記の記述を加える
[state -3,情報取得];摩擦・重力測定
type = null
triggerall = var(59)&&RoundState=2&&Alive
trigger1 = EnemyNear,StateType=S
trigger1 = fvar(30):=EnemyNear,Const(movement.stand.friction)
trigger2 = EnemyNear,StateType=C
trigger2 = fvar(30):=EnemyNear,Const(movement.crouch.friction)
trigger3 = EnemyNear,StateType=A
trigger3 = fvar(30):=EnemyNear,GetHitVar(yaccel)
persistent = 1
IgNoreHitPause = 1
PauseMoveTime = 9999
SuperMoveTime = 9999
[state -3,情報取得];速度
type = null
triggerall = var(59)&&RoundState=2&&Alive
trigger1 = fvar(31):=abs(EnemyNear,GetHitVar(xvel))&&0
trigger2 = fvar(32):=P2BodyDist X&&0
trigger3 = fvar(33):=abs(EnemyNear,Vel X)&&0
persistent=1
IgNoreHitPause=1
PauseMoveTime=9999
SuperMoveTime=9999
・次に、triggerall = P2BodyDist X = [5,25]とかしている部分を、下記のtriggerに入れ替える
※例 攻撃判定が出るのがステートの開始から13フレーム目で、横方向のリーチが25ピクセルの技の場合
triggerall = var(40):=Ceil(fvar(31))+Ceil(fvar(31)*fvar(30)**1)+Ceil(fvar(31)*fvar(30)**2)+Ceil(fvar(31)*fvar(30)**3)+Ceil(fvar(31)*fvar(30)**4)+Ceil(fvar(31)*fvar(30)**5)||1
triggerall = var(40):=var(40)+Ceil(fvar(31)*fvar(30)**6)+Ceil(fvar(31)*fvar(30)**7)+Ceil(fvar(31)*fvar(30)**8)+Ceil(fvar(31)*fvar(30)**9)+Ceil(fvar(31)*fvar(30)**10)||1
triggerall = var(40):=var(40)+Ceil(fvar(31)*fvar(30)**11)+Ceil(fvar(31)*fvar(30)**12)||1
triggerall = Floor(fvar(32)+var(40))=[-5,25]
もし僕の方法を参考にしたいという方が居るなら、この部分をコピー&ペーストして頂ければそれでOK(のはず)です。
以下に、細かく原理を解説しようと思います。
※1 当然ながら、使用しているvar(40)、fvar(30)~fvar(33)が未使用なのを確認してからにしましょう。
※2 winmugenは一行に書ける記述が決まっているのでいちいち変数に格納していますが、1.0以降なら必要ないかもしれません。
まず大前提として、MUGENはゲームとはいえど、基本的には速度や距離といったものは高校で習うような物理法則に沿っています。
つまり下図1の場合だと、
開始時のA・B間の距離X[m]でAがV[m/s]でBから離れるとき、t[sec]後のA・B間の距離X’[m]は
X’ = X + V ・ t
となる訳ですね。
これをMUGENのtriggerに当てはめると、距離Xは『P2BodyDist X』に、相手の速度Vは『Enemy,Vel X』と言い換えることが出来ます。
また、[m]などの距離の単位は[ピクセル]、[sec]などの時間の単位は[フレーム]です。
つまり、相手Bが近づいてくるときn[フレーム]後の相手との距離をMUGENっぽく書くと
Trigger1 = P2BodyDist X + Enemy,Vel X * n
と なります。
Vel X = 1 というのは、1フレームごとに1ピクセル進むという意味なのです。10フレーム後には10ピクセル進みます。
なんだこれで完成じゃん!と思うかもしれませんが、ここからが面倒なところ。
前提として『自分が相手にコンボ中』である訳なので、自分の攻撃が当たってヒットストップが発生している状態です。
ヒットストップ中は当然相手も止まってるので、Vel Xはゼロです。
これでは、相手との距離がどのぐらい離れるのか取得することが出来ないので、
Vel Xの代わりに『Enemy,GetHitVar(xvel)』を使います。
これは、自分のHitDefで設定した相手の仰け反り中の初速を参照するtriggerなのですが、
困ったことにEnemy,Vel Xと逆の符号を返すことに注意しましょう
(Enemy,Vel Xは、相手が自分に近づくときはプラス。Enemy,GetHitVar(xvel)は、相手が自分に近づくときはマイナス)。
次に、相手が食らいモーション中ということはノックバックが発生して仰け反っている状態な訳なので、
この時、地上にいるなら毎フレーム摩擦がかかります。
普通の物理だと、重量や地面の状態から摩擦係数を計算しなければ正確な移動距離は算出できませんが、
MUGENだと相手の[Movement]に設定されている『friction』の数値だけ、毎フレーム減速する処理が行われます。
しかも面倒くさいことにノックバックが始まるフレームには摩擦は適応されないようです。
つまり、1フレーム後の相手の速度はEnemy,GetHitVar(xvel)で参照できますが、
2フレーム後の相手の速度は
Enemy,GetHitVar(xvel) * Enemy,Const(movement.stand.friction)
となり、さらに3フレーム後の相手の速度は
Enemy,GetHitVar(xvel) * Enemy,Const(movement.stand.friction) * Enemy,Const(movement.stand.friction)
こうなります。
まとめると、nフレーム後の相手の速度は
Enemy,GetHitVar(xvel) * Enemy,Const(movement.stand.friction) ** n - 1
これでようやく、速度が取得できました。
※MUGENにおける『**』は累乗の意味。「1**1」は1の1乗、「3**5」は3の5乗。
これで終わりではなく、nフレーム後の相手との距離が知りたいので更なる計算が必要です。
ノックバックが終わるまでの毎フレーム『Enemy,GetHitVar(xvel) * Enemy,Const(movement.stand.friction) ** n - 1』の速度で
自分との距離が開いていくということなので、
1フレーム後の相手との距離は
P2BodyDist X + Enemy,GetHitVar(xvel)
2フレーム後の相手との距離は
P2BodyDist X + Enemy,GetHitVar(xvel) + (Enemy,GetHitVar(xvel) * Enemy,Const(movement.stand.friction) ** 1)
3フレーム後の相手との距離は
P2BodyDist X + Enemy,GetHitVar(xvel) + (Enemy,GetHitVar(xvel) * Enemy,Const(movement.stand.friction) ** 1) + (Enemy,GetHitVar(xvel) * Enemy,Const(movement.stand.friction) ** 2)
・・・
これをコンボで出したい技の攻撃判定が出るフレームまでやれば、完璧に相手との離れる距離が取得できる(はず)です。
この計算を変数に格納し分かりやすくしたものが、上記のテンプレートです。
←TOPへ