Как можно сократить данный код?

Рейтинг: 1Ответов: 2Опубликовано: 04.03.2023

Я только начал изучение языков программирование и хотелось бы научится писать красиво и коротко, поэтому буду благодарен узнать как можно сократить следующий код:

int SpriteAnimation()
{
if (x + y != 2)
{
    if (x <= 12)
    {
        tcordLeft = (x - 1) * scale,
        tcordUp = (y - 1) * scale,
        tcordRight = x * scale,
        tcordDown = y * scale;
    }
    else
    {
        x = 0;
        if (y == 12)
        {
            tcordLeft = (x - 1) * scale,
            tcordUp = (y - 1) * scale,
            tcordRight = x * scale,
            tcordDown = y * scale;
            y = 1;
        }
        else
        {
            y++;
        }
    }
}
else
{
    tcordLeft = scale - scale,
    tcordUp = scale - scale,
    tcordRight = scale,
    tcordDown = scale;
}
x++;
return 0;
}

Вот все значение переменных:

int x = 1, y = 1; //номера спрайтов по оси x и y
float spritesheetsize = 0.1152, spritesize = 0.96; 
//spritesheetsize - размер спрайтлиста (1152 пикселя в ширину и высоту)
//spritesize - размер одного спрайта (96 пикселей в ширину и высоту)
float scale = spritesize / spritesheetsize * 0.1 * 0.1;
//scale - масштабирование под нужный размер отображение
float tcordLeft,
  tcordUp,
  tcordRight,
  tcordDown;
//текстурные координаты для отображение нужного спрайта из спрайтлиста

Думаю я написал много лишнего и этот код можно уменьшить но я не знаю как )

Ответы

▲ 4Принят

Прежде чем сокращать код, надо разобраться что он делает. Ниже программа печатающая что происходит внутри SpriteAnimation:

#include <iostream>

using namespace std;

int x = 1, y = 1; //номера спрайтов по оси x и y
float spritesheetsize = 0.1152, spritesize = 0.96; 
//spritesheetsize - размер спрайтлиста (1152 пикселя в ширину и высоту)
//spritesize - размер одного спрайта (96 пикселей в ширину и высоту)
float scale = spritesize / spritesheetsize * 0.1 * 0.1;
//scale - масштабирование под нужный размер отображение
float tcordLeft,
  tcordUp,
  tcordRight,
  tcordDown;
//текстурные координаты для отображение нужного спрайта из спрайтлиста


void dump() {
    cout << ", x = "          << x
         << ", y = "          << y
         << ", tcordLeft = "  << tcordLeft
         << ", tcordUp = "    << tcordUp
         << ", tcordRight = " << tcordRight
         << ", tcordDown = "  << tcordDown
    ;
}

int SpriteAnimation()
{
    cout << "SpriteAnimation, x = " << x << ", y = " << y;
    if (x + y != 2)
    {
        if (x <= 12)
        {
            tcordLeft = (x - 1) * scale,
            tcordUp = (y - 1) * scale,
            tcordRight = x * scale,
            tcordDown = y * scale;
            dump();
        }
        else
        {
            x = 0;
            if (y == 12)
            {
                tcordLeft = (x - 1) * scale,
                tcordUp = (y - 1) * scale,
                tcordRight = x * scale,
                tcordDown = y * scale;
                dump();
                y = 1;
            }
            else
            {
                y++;
            }
        }
    }
    else
    {
        tcordLeft = scale - scale,
        tcordUp = scale - scale,
        tcordRight = scale,
        tcordDown = scale;
        dump();
    }
    x++;
    cout << '\n';
    return 0;
}

int main() {
    for (int i = 0; i < 200; ++i) {
        SpriteAnimation();
    }
}

Каждый раз функция обновляет координаты спрайта, но иногда пропускает итерацию. В предпоследней строке выдержки координаты спрайта не меняются. Если у нас анимация, она будет заикаться:

SpriteAnimation, x = 1, y = 1, x = 1, y = 1, tcordLeft = 0, tcordUp = 0, tcordRight = 0.0833333, tcordDown = 0.0833333
SpriteAnimation, x = 2, y = 1, x = 2, y = 1, tcordLeft = 0.0833333, tcordUp = 0, tcordRight = 0.166667, tcordDown = 0.0833333
SpriteAnimation, x = 3, y = 1, x = 3, y = 1, tcordLeft = 0.166667, tcordUp = 0, tcordRight = 0.25, tcordDown = 0.0833333
SpriteAnimation, x = 4, y = 1, x = 4, y = 1, tcordLeft = 0.25, tcordUp = 0, tcordRight = 0.333333, tcordDown = 0.0833333
SpriteAnimation, x = 5, y = 1, x = 5, y = 1, tcordLeft = 0.333333, tcordUp = 0, tcordRight = 0.416667, tcordDown = 0.0833333
SpriteAnimation, x = 6, y = 1, x = 6, y = 1, tcordLeft = 0.416667, tcordUp = 0, tcordRight = 0.5, tcordDown = 0.0833333
SpriteAnimation, x = 7, y = 1, x = 7, y = 1, tcordLeft = 0.5, tcordUp = 0, tcordRight = 0.583333, tcordDown = 0.0833333
SpriteAnimation, x = 8, y = 1, x = 8, y = 1, tcordLeft = 0.583333, tcordUp = 0, tcordRight = 0.666667, tcordDown = 0.0833333
SpriteAnimation, x = 9, y = 1, x = 9, y = 1, tcordLeft = 0.666667, tcordUp = 0, tcordRight = 0.75, tcordDown = 0.0833333
SpriteAnimation, x = 10, y = 1, x = 10, y = 1, tcordLeft = 0.75, tcordUp = 0, tcordRight = 0.833333, tcordDown = 0.0833333
SpriteAnimation, x = 11, y = 1, x = 11, y = 1, tcordLeft = 0.833333, tcordUp = 0, tcordRight = 0.916667, tcordDown = 0.0833333
SpriteAnimation, x = 12, y = 1, x = 12, y = 1, tcordLeft = 0.916667, tcordUp = 0, tcordRight = 1, tcordDown = 0.0833333
SpriteAnimation, x = 13, y = 1
SpriteAnimation, x = 1, y = 2, x = 1, y = 2, tcordLeft = 0, tcordUp = 0.0833333, tcordRight = 0.0833333, tcordDown = 0.166667
...

Когда мы добежали до края листа и переходим на его начало, вместо заикания обращение к отрицательным координатам. Средняя строка:

...
SpriteAnimation, x = 11, y = 12, x = 11, y = 12, tcordLeft = 0.833333, tcordUp = 0.916667, tcordRight = 0.916667, tcordDown = 1
SpriteAnimation, x = 12, y = 12, x = 12, y = 12, tcordLeft = 0.916667, tcordUp = 0.916667, tcordRight = 1, tcordDown = 1
SpriteAnimation, x = 13, y = 12, x = 0, y = 12, tcordLeft = -0.0833333, tcordUp = 0.916667, tcordRight = 0, tcordDown = 1
SpriteAnimation, x = 1, y = 1, x = 1, y = 1, tcordLeft = 0, tcordUp = 0, tcordRight = 0.0833333, tcordDown = 0.0833333
SpriteAnimation, x = 2, y = 1, x = 2, y = 1, tcordLeft = 0.0833333, tcordUp = 0, tcordRight = 0.166667, tcordDown = 0.0833333
...

Код пытается перебирать спрайты на атласе и, в общем, делает это довольно успешно. Но есть две ошибки, которые надо исправить. Мне показалось проще не исправлять ваш код, а написать новый. Получилось так:

#include <iostream>

using namespace std;

const int atlas_size = 1152;
const int sprite_size = 96;
const float scale = sprite_size / static_cast<float>(atlas_size);
const int n = atlas_size / sprite_size;

int x = 0; // номер спрайта по горизонтали
int y = 0; // номер спрайта по вертикали

//текстурные координаты для отображения нужного спрайта из спрайтлиста
float tcordLeft;
float tcordUp;
float tcordRight;
float tcordDown;

void dump() {
    cout << ", x = "          << scale * x
         << ", y = "          << scale * y
         << ", tcordLeft = "  << tcordLeft
         << ", tcordUp = "    << tcordUp
         << ", tcordRight = " << tcordRight
         << ", tcordDown = "  << tcordDown
    ;
}

void SpriteAnimation() {
    cout << "SpriteAnimation, x = " << x << ", y = " << y;

    tcordLeft  = scale * x      ;
    tcordUp    = scale * y      ;
    tcordRight = scale * (x + 1);
    tcordDown  = scale * (y + 1);
    dump();

    ++x;
    if (x >= n) {
        x = 0;
        ++y;
        if (y >= n) {
            y = 0;
        }
    }

    cout << '\n';
}

int main() {
    for (int i = 0; i < 200; ++i) {
        SpriteAnimation();
    }
}

Если убрать всю отладку:

const int atlas_size = 1152;
const int sprite_size = 96;
const float scale = sprite_size / static_cast<float>(atlas_size);
const int n = atlas_size / sprite_size;

int x = 0; // номер спрайта по горизонтали
int y = 0; // номер спрайта по вертикали

//текстурные координаты для отображения нужного спрайта из спрайтлиста
float tcordLeft;
float tcordUp;
float tcordRight;
float tcordDown;

void SpriteAnimation() {
    tcordLeft  = scale * x      ;
    tcordUp    = scale * y      ;
    tcordRight = scale * (x + 1);
    tcordDown  = scale * (y + 1);

    ++x;
    if (x >= n) {
        x = 0;
        ++y;
        if (y >= n) {
            y = 0;
        }
    }
}

Не удержусь от соблазна показать ещё один короткий код. Он, кажется, довольный быстрый. В среднем 1.08(3) проверки и 0.9930(5) сложений на итерацию:

const int atlas_size = 1152;
const int sprite_size = 96;
const float scale = sprite_size / static_cast<float>(atlas_size);

//текстурные координаты для отображения нужного спрайта из спрайтлиста
float tcordLeft = 0;
float tcordUp = 0;
float tcordRight = scale;
float tcordDown = scale;

void SpriteAnimation() {
    if (tcordRight < 1 - scale / 2) {
        tcordLeft = tcordRight;
        tcordRight += scale;
    } else {
        tcordLeft = 0;
        tcordRight = scale;

        if (tcordDown < 1 - scale / 2) {
            tcordUp = tcordDown;
            tcordDown += scale;
        } else {
            tcordUp = 0;
            tcordDown = scale;
        }
    }
}
▲ 2

Ну, если не ошибся (делал без особых проверок, а писать все обвязки для проверки не хотелось), то можно примерно так:

int SpriteAnimation()
{
    if ( x+y == 12 ) {
        tcordLeft  = tcordUp   = 0;
        tcordRight = tcordDown = scale;
    }
    else
    {
        if (x > 12) x = 0;
        if (x <= 12 || y == 12)
        {
            tcordLeft = (x - 1) * scale;
            tcordUp   = (y - 1) * scale;
            tcordRight = x * scale;
            tcordDown  = y * scale;
        }
        if (x > 12) y += 1 - 12*(y == 12);
    }
    x++;
    return 0;
}

Внимание: за ошибки автора в исходном коде ответственности не несу. Переделывал именно код автора.