Как перевернуть текстуру в VertexArray?

У меня есть анимация спрайтов, нарисованная с использованием массива вершин. В качестве примера предположим, что у меня есть стрелка, указывающая вправо с простой анимацией. Я хотел бы иметь возможность перевернуть текстуру по оси x, чтобы стрелка также могла указывать влево без необходимости удваивать размер моего спрайт-листа.

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

#include <SFML/Graphics.hpp>
#include <iostream>

int main()
{
    // CREATE THE WINDOW

    sf::RenderWindow window(sf::VideoMode(200, 200), "Arrow");
    window.setFramerateLimit(20);

    // CREATE GRAPHICS

    sf::Texture texArrow;
    texArrow.loadFromFile("Arrow.png");

    sf::VertexArray vaArrow;
    sf::RenderStates rsArrow;
    rsArrow.texture = &texArrow;

    vaArrow.setPrimitiveType(sf::Quads);
    vaArrow.resize(4);

    vaArrow[0].position = sf::Vector2f(0, 0);
    vaArrow[1].position = sf::Vector2f(100, 0);
    vaArrow[2].position = sf::Vector2f(100, 100);
    vaArrow[3].position = sf::Vector2f(0, 100);

    vaArrow[0].texCoords = sf::Vector2f(0, 0);
    vaArrow[1].texCoords = sf::Vector2f(100, 0);
    vaArrow[2].texCoords = sf::Vector2f(100, 100);
    vaArrow[3].texCoords = sf::Vector2f(0, 100);

    // ARROW DIRECTION STATES

    enum Directions { right, left};
    Directions dir = right;

    float AnimationFrame = 0;

    // GAME LOOP

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed) { window.close(); }

            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { dir = right; }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { dir = left; }
        }

        // UPDATE

        switch (dir)
        {
            case right: // NORMAL

                std::cout << "Arrow is now pointing RIGHT" << std::endl;

                vaArrow[0].texCoords = sf::Vector2f(AnimationFrame * 100        ,   0);
                vaArrow[1].texCoords = sf::Vector2f(AnimationFrame * 100 + 100  ,   0);
                vaArrow[2].texCoords = sf::Vector2f(AnimationFrame * 100 + 100  ,   100);
                vaArrow[3].texCoords = sf::Vector2f(AnimationFrame * 100        ,   100);

                break;

            case left: // FLIPPED

                std::cout << "Arrow is now pointing LEFT" << std::endl;

                // THIS IS WHAT I HAVE TRIED BUT IT DOESN'T WORK:

                vaArrow[0].texCoords = sf::Vector2f((AnimationFrame * 100) * -1         ,   0);
                vaArrow[1].texCoords = sf::Vector2f((AnimationFrame * 100 + 100) * -1   ,   0);
                vaArrow[2].texCoords = sf::Vector2f((AnimationFrame * 100 + 100) * -1   ,   100);
                vaArrow[3].texCoords = sf::Vector2f((AnimationFrame * 100) * -1         ,   100);

                break;
        }

        AnimationFrame++;

        if (AnimationFrame == 5) { AnimationFrame = 0; } // Always loop 0 1 2 3 4

        // RENDER

        window.clear();
        window.draw(vaArrow, rsArrow);
        window.display();
    }

    return 0;
}

Таблица спрайтов для примера:

Стрелка


person Nathaniel G.M.    schedule 14.12.2017    source источник


Ответы (1)


Есть много дней, чтобы решить эту проблему, но ваша настоящая идея не так уж далека. Вы заметили, что вы растягиваете один конец стрелки по всему квадрицепсу?

Решение довольно простое: по умолчанию. Текстуры не повторяются, они зажаты (имеется в виду, что пиксели по краям повторяются бесконечно), что и вызывает замеченный вами глюк.

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

texArrow.setRepeated(true);
person Mario    schedule 14.12.2017