Как вы переворачиваете текстуру в VertexArray?

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

Я знаю, что это возможно с помощью спрайтов с использованием отрицательного масштабного коэффициента, но в тех случаях, когда мне нужно использовать vertexarray, я хотел бы знать, как это возможно. Я попытался дать 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;
}

Spritesheet для примера:

Стрела

0

Решение

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

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

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

texArrow.setRepeated(true);
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]