Тёмная тема
Не придумал более понятного названия темы
Дано:
// Массив текстур персонажа (8 направлений), 0 - север, 1 - северо-восток, ... FrameInfo info[8]; // Направление стика vec2 dir;
Как бы наиболее быстрым способом перевести dir в индекс массива info?
Нагуглил такую функцию:
float DiamondAngle(float y, float x) { if ( y >= 0.0f) return ( x >= 0.0f ? y / ( x + y) : 1.0f - x / ( -x + y)); else return ( x < 0.0f ? 2.0f - y / ( -x - y) : 3.0f + x / ( x - y)); }
Получается примерно так:
dir.x = Buttons.RIGHT - Buttons.LEFT; dir.y = Buttons.UP - Buttons.DOWN; // Поворот вектора на -90 градусов float tmp_x = dir.y; float tmp_y = -dir.x; int current_picture = int(4.0f - DiamondAngle( tmp_y, tmp_x)) * 2.0f); if ( current_picture == 8) current_picture = 0; // Костыль
Какие ещё есть варианты?
Есть ещё мысль запаковать направление в целое число и написать длинный switch .. case.
Как вариант.
Перевести вектор направления стика в угол - angle=Atan2( dir->y,dir->x )
Сконвертировать его в формат 0..360 градусов.
FrameInfo current = info[ Cast<Int>( angle / 45.0f ) ]
Нашёл такую аппроксимацию:
// Approximates atan2(y, x) normalized to the [0,4) range // with a maximum error of 0.1620 degrees float normalized_atan2(float y, float x ) { static const uint32_t sign_mask = 0x80000000; static const float b = 0.596227f; // Extract the sign bits uint32_t ux_s = sign_mask & ( uint32_t &)x; uint32_t uy_s = sign_mask & ( uint32_t &)y; // Determine the quadrant offset float q = ( float)( ( ~ux_s & uy_s ) >> 29 | ux_s >> 30 ); // Calculate the arctangent in the first quadrant float bxy_a = ::fabs( b * x * y ); float num = bxy_a + y * y; float atan_1q = num / ( x * x + bxy_a + num ); // Translate it to the proper quadrant uint32_t uatan_2q = ( ux_s ^ uy_s) | ( uint32_t &)atan_1q; return q + ( float &)uatan_2q; }
В принципе работает.