0

我有一个使用顶点数组绘制的 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;
}

示例的精灵表:

箭

4

1 回答 1

1

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

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

因此,要使您的方法发挥作用,您所要做的就是设置要重复的纹理:

texArrow.setRepeated(true);
于 2017-12-14T18:40:51.020 回答