ゲームが作れるようになるまでがんばる日記

ゲーム制作のことを中心にゲームに関することを書いています

ヒットストップの計算

最近プレイしているモンスターハンターワールド。大剣でモンスターを斬る感覚が気持ちいい。その気持ちよさを表現している一つがヒットストップ。剣がモンスターに当たった瞬間などにモーションが一瞬止まったり、スローモーションになったりする表現。このヒットストップを試しに実装してみた。


tが0.0から1.0に変化するときに、ヒットストップを考慮したtを求める関数が次のとおり。

float CalcHitStop(float t, float t0, float t1, float k) {
    if(t<t0) { return t; }
    if(t0<=t && t<=t1) { return k * (t-t0) + t0; }
    return ( (1.0f- k * (t1-t0) - t0) / (1.0f - t1) ) * (t-t1) + (k * (t1-t0) + t0);
}

tが今の経過時間、t0がヒットストップが始まる時間、t1がヒットストップが終わる時間、kがヒットストップでどのくらいの遅さになるかの変化率。0.5で半分の速度になり、0.0で一時停止となる。
ヒットストップが終わった後は遅くなった分、速くなり、全体の時間は変わらない。グラフにすると次のとおり。

例えば、0.3秒のときにヒットストップが始まり、半分の速度で動き、0.6秒のときにヒットストップが終わる場合は次のようになる。

float t;
t = CalcHitStop(t, 0.3, 0.6, 0.5);

ヒットストップ後に速度が変わらない場合は次の関数。

float CalcHitStop2(float t, float t0, float t1, float k)	{
    if(t<t0) { return t; }
    if(t0<=t && t<=t1) { return k * (t-t0) + t0; }
    return  (t-t1) + (k * (t1-t0) + t0);
}

こちらはヒットストップの時間分、全体の時間が長くなる。グラフにすると次のとおり。

終わりの時間は計算結果が1.0になるか判定するか、ヒットストップの時間と変化率から計算して求めれば良い。


このようにして求めたtをアニメーションの再生に使ったり、キャラクターの移動に使えばヒットストップの表現ができる。