Войти
ПрограммированиеФорум2D графика и изометрия

Направление персонажа и индекс в атласе

#0
7:31, 24 мар 2022

Не придумал более понятного названия темы

Дано:

// Массив текстур персонажа (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; // Костыль

Какие ещё есть варианты?

#1
9:50, 24 мар 2022

Есть ещё мысль запаковать направление в целое число и написать длинный switch .. case.

#2
(Правка: 11:05) 11:04, 24 мар 2022

Как вариант.

Перевести вектор направления стика в угол - angle=Atan2( dir->y,dir->x )
Сконвертировать его в формат 0..360 градусов.

FrameInfo current = info[ Cast<Int>( angle / 45.0f ) ]
#3
14:29, 24 мар 2022

Нашёл такую аппроксимацию:

// 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;
} 

В принципе работает.

ПрограммированиеФорум2D графика и изометрия