少し苦戦したのでメモ書き。
c++20です。
やり方
1フレーム前と現在フレームの入力ベクトルを比較し、
プレイヤーの向きがどの程度変わったのかを算出します。
#include <cmath>
#include <numbers>
// 2次元ベクトル構造体
struct Vector2
{
float x;
float y;
// 内積
float Dot(const Vector2& arg_v)
{
return x * v.x + y * v.y;
}
}
int main(void)
{
// 1フレーム前の入力ベクトル
Vector2 input_old{};
// 現在フレームの入力ベクトル
Vector2 input_current{};
while(GetIsTrigger(DIK_R) != true)
{
// 入力ベクトルの取得(正規化済み)
input_current = GetInput();
// 現在の入力ベクトルと、1フレーム前の入力ベクトルとの内積値
const float dot = input_current.Dot(input_old);
// 内積値からラジアンを取得
const float radian_temp = std::acosf(dot);
// プレイヤーを回転させるのに使用するラジアン
float radian_rotate = radian_temp;
if(input_current.x < 0)
{
const float pi = std::numbers::pi;
// 180度 + 180度超えていた差分
radian_rotate = pi + (pi - radian_temp);
}
// プレイヤーを回転させる
player.rotate = radian_rotate;
input_old = input_current;
}
return 0;
}
解説
苦戦したのは、std::acosで算出されるラジアンの範囲が、0~πまでしかない点。
入力ベクトルが { 0, -1 } の時、算出されるラジアンは最大値のπとなり、
それより値が大きくなることはない。(本当は2πまでは大きくなり続けてほしい。)
なので、入力ベクトルのx成分が 0 より小さくなった時のラジアンが、
2πまで大きくなるようにした。
簡単な図説
radian_rotate(input_old から input_current までの 角度)の算出
radian_rotate = π + (π - radian_temp);
最後に
※GetInput()は入力を取得する関数です。
何か間違い等あれば指摘をお願いします。