你如何在VertexArray中翻转纹理?

时间:2017-12-14 18:19:02

标签: c++ sfml sprite-sheet vertex-array

我有一个使用顶点阵列绘制的spritesheet动画。举个例子,假设我有一个箭头指向右边有一个简单的动画。我希望能够在x轴上翻转纹理,这样箭头也可以指向左边而不需要加倍我的spritesheet的大小。

我知道通过使用负比例因子可以使用精灵,但在我必须使用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:

Arrow

1 个答案:

答案 0 :(得分:1)

有很多天可以解决这个问题,但你的实际想法并不是那么遥远。您是否注意到您基本上是在整个四边形上拉伸箭头的一端?

解决方案非常简单:默认情况下。纹理不会重复,它们被夹住(意味着边缘上的像素无限重复),这会导致你注意到的故障。

所以你需要做的就是设置重复的纹理:

<__main__.A object at 0x7f64e65c62e8>
None