У меня есть анимация 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 для примера:
Есть много дней, чтобы решить это, но ваша настоящая идея не так уж далека. Вы заметили, что вы в основном растягиваете один конец стрелки над всем своим квадом?
Решение довольно простое: по умолчанию. Текстуры не повторяются, они зажаты (это означает, что пиксели по краям повторяются бесконечно), что вызывает заметный сбой.
Так что все, что вам нужно сделать, чтобы ваш подход работал, это установить текстуру для повторения:
texArrow.setRepeated(true);
Других решений пока нет …