SFML原地翻转图像

⌚Time: 2024-09-03 22:49:00

👨‍💻Author: Jack Ge

使用sfml绘制精灵时,经常需要水平翻转实现转向。

我尝试使用scale函数直接进行翻转

m_rectangleShape->scale(-1.f, 1.f);

得到的图像是翻转了,但是没有在原地。而是围绕一根轴线进行的翻转。这根轴不在中心位置,而是在左侧,确切的说,sfml的一切旋转,缩放,位置,都是围绕实体左上点处为原点进行的。

好在sfml有设定原点的函数setOrigin,如果我把图像实体的原点设置在中心处再翻转呢,还是没有按照原地翻转,依旧是翻转后偏移了一些位置,只不过没有直接缩放偏移的严重而已,只偏移了之前的1/2.

m_rectangleShape->setOrigin(sf::Vector2f(m_rectangleShape->getLocalBounds().width/2, 0));
//设置缩放
m_rectangleShape->scale(-1.f, 1.f);

原理是,sfml的原点被改变了,位置也会受影响。sfml教程里的话:

By default, entities are positioned relative to their top-left corner. We'll see how to change that with the 'origin' property later.

所以正确的方式是将水平原点设置到图像实体的宽度,这样就可以实现原地水平的翻转

m_rectangleShape->setOrigin(sf::Vector2f(m_rectangleShape->getLocalBounds().width, 0));
//设置缩放
m_rectangleShape->scale(-1.f, 1.f);

我可以画图解释,第一张图是设置原点之前图片位置,第二张图是设定原点后图片的位置,第三张图是翻转后图片的位置。所以实现了原地翻转。

在sfml的Drawable类中,在draw函数里可以这样写,通过一个标志位m_isFlip来决定显示的图片是否翻转。

    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const{
        
        //翻转动画
        if (m_isFlip){
            //设置原点
            m_rectangleShape->setOrigin(sf::Vector2f(m_rectangleShape->getLocalBounds().width, 0));
            //设置缩放
            m_rectangleShape->scale(-1.f, 1.f);

        }

        target.draw(*m_rectangleShape, states);

        //恢复翻转
        if (m_isFlip){
            //恢复缩放
            m_rectangleShape->scale(-1.f, 1.f);
            //恢复原点
            m_rectangleShape->setOrigin(sf::Vector2f(0, 0));
        }
    }