SFML2.6 图形模块--位置、旋转、缩放:实体变换

变换SFML实体

所有SFML类(精灵、文本、形状)都使用相同的界面进行转换:sf::Transformable。这个基类提供了一个简单的API来移动、旋转和缩放你的实体。它不提供最大的灵活性,而是定义了一个易于理解和使用的接口,覆盖了99%的所有用例——对于剩下的1%,请参阅最后一章。

sf::Transformable(以及所有派生类)定义了四个属性:位置、旋转、比例和原点。它们都有各自的getter和setter。这些变换组件都是相互独立的:如果你想改变实体的方向,你只需要设置它的旋转属性,你不必关心当前的位置和比例。

位置

位置是实体在2D世界中的位置。我认为它不需要更多的解释。 😃

// 'entity' can be a sf::Sprite, a sf::Text, a sf::Shape or any other transformable class

// set the absolute position of the entity
entity.setPosition(10.f, 50.f);

// move the entity relatively to its current position
entity.move(5.f, 5.f);

// retrieve the absolute position of the entity
sf::Vector2f position = entity.getPosition(); // = (15, 55)

在这里插入图片描述
默认情况下,实体是相对于它们的左上角定位的。我们稍后将看到如何使用“原点”属性更改它。

旋转

旋转是实体在二维世界中的方向。它以度数定义,按顺时针顺序(因为在SFML中,Y轴向下指向)。

// 'entity' can be a sf::Sprite, a sf::Text, a sf::Shape or any other transformable class

// set the absolute rotation of the entity
entity.setRotation(45.f);

// rotate the entity relatively to its current orientation
entity.rotate(10.f);

// retrieve the absolute rotation of the entity
float rotation = entity.getRotation(); // = 55

在这里插入图片描述
请注意,当您调用 getRotation 时,SFML始终以[0,360)的范围返回角度。

与位置一样,旋转默认情况下围绕左上角执行,但可以通过设置原点来更改。

缩放

比例因子允许调整实体的大小。默认比例为1。将其设置为小于1的值会使实体变小,大于1的值会使实体变大。也可以使用负的比例值,以便您可以镜像实体。

// 'entity' can be a sf::Sprite, a sf::Text, a sf::Shape or any other transformable class

// set the absolute scale of the entity
entity.setScale(4.f, 1.6f);

// scale the entity relatively to its current scale
entity.scale(0.5f, 0.5f);

// retrieve the absolute scale of the entity
sf::Vector2f scale = entity.getScale(); // = (2, 0.8)

在这里插入图片描述

原点

原点是三个其他变换的中心点。实体的位置是它的原点的位置,它的旋转是围绕原点进行的,并且比例也相对于原点应用。默认情况下,它是实体的左上角(点(0,0)),但是您可以将其设置为实体的中心或实体的任何其他角落。

为了简化事情,所有三个变换组件只有一个原点。这意味着您无法将实体相对于其左上角定位,同时围绕其中心旋转。如果您需要执行此类操作,请查看下一章节。

// 'entity' can be a sf::Sprite, a sf::Text, a sf::Shape or any other transformable class

// set the origin of the entity
entity.setOrigin(10.f, 20.f);

// retrieve the origin of the entity
sf::Vector2f origin = entity.getOrigin(); // = (10, 20)

请注意,更改原点也会更改实体在屏幕上绘制的位置,即使其位置属性没有更改。如果您不理解原因,请再次阅读本教程!

转换你自己的类

sf::Transformable不仅适用于SFML的类,它也可以是你自己的类的基类或成员。

class MyGraphicalEntity : public sf::Transformable
{
    // ...
};

MyGraphicalEntity entity;
entity.setPosition(10.f, 30.f);
entity.setRotation(110.f);
entity.setScale(0.5f, 0.2f);

如果你需要获取实体的最终变换(通常在绘制它时需要),可以调用getTransform函数。该函数返回一个sf::Transform对象。下面将解释如何使用它来转换SFML实体。

如果你不需要或不想使用sf::Transformable接口提供的完整函数集,可以将其作为成员使用,并在其上提供自己的函数。它不是一个抽象类,因此可以实例化它,而不仅仅是将其用作基类。

自定义变换

sf::Transformable类易于使用,但也具有一定的限制。某些用户可能需要更灵活的功能。他们可能需要将最终变换指定为单个变换的自定义组合。针对这些用户,有一个更低级别的类可用:sf :: Transform。它不过是一个3x3矩阵,因此它可以表示2D空间中的任何变换。

有许多构造sf::Transform的方法:

  • 使用最常见变换(平移、旋转、缩放)的预定义函数
  • 通过组合两个变换
  • 通过直接指定其9个元素

以下是一些示例:

// the identity transform (does nothing)
sf::Transform t1 = sf::Transform::Identity;

// a rotation transform
sf::Transform t2;
t2.rotate(45.f);

// a custom matrix
sf::Transform t3(2.f, 0.f, 20.f,
                 0.f, 1.f, 50.f,
                 0.f, 0.f, 1.f);

// a combined transform
sf::Transform t4 = t1 * t2 * t3;

您也可以将几个预定义变换应用于同一个变换。它们将按顺序依次组合。请注意,通过组合多个变换来转换对象等效于以相反的顺序应用每个操作。最后一个操作(在此处为缩放)首先应用,并且将受到代码上方的操作的影响(例如第二个操作可能是translate(-10.f,50.f))。

sf::Transform t;
t.translate(10.f, 100.f);
t.rotate(90.f);
t.translate(-10.f, 50.f);
t.scale(0.5f, 0.75f);

回到重点:如何将自定义变换应用于图形实体?简单:将它传递给draw函数即可。

window.draw(entity, transform);

…实际上是以下代码的简写:

sf::RenderStates states;
states.transform = transform;
window.draw(entity, states);

如果你的实体是 sf::Transformable(如:sprite、text、shape),它包含自己的内部 transform,那么这两个 transform 会合并成最终的 transform。

边界框

对于已经进行过变换并且绘制出来的实体,你可能想要执行一些计算,例如检查它们之间是否发生了碰撞。

SFML 实体可以提供它们的边界框。边界框是一个最小矩形,它包含了实体的所有点,并且边缘与 X 和 Y 轴对齐。
在这里插入图片描述
边界框在实现碰撞检测时非常有用:可以非常快速地检查点或另一个轴对齐矩形与其之间的关系,并且其面积足够接近真实实体的面积,从而提供了一个很好的近似值。

// get the bounding box of the entity
sf::FloatRect boundingBox = entity.getGlobalBounds();

// check collision with a point
sf::Vector2f point = ...;
if (boundingBox.contains(point))
{
    // collision!
}

// check collision with another box (like the bounding box of another entity)
sf::FloatRect otherBox = ...;
if (boundingBox.intersects(otherBox))
{
    // collision!
}

函数被命名为getGlobalBounds,因为它返回实体在全局坐标系中的边界框,即在应用所有变换(位置、旋转、缩放)后的边界框。

还有另一个函数getLocalBounds,它返回实体在其本地坐标系中的边界框(在应用变换之前)。例如,可以使用此函数获取实体的初始大小或执行更特定的计算。

对象层次结构(场景图)

使用前面介绍的自定义变换,实现对象层次结构(场景图)变得非常简单,其中子对象相对于其父对象进行变换。在绘制它们时,您只需要将从父对象到子对象的组合变换传递即可,一直到达最终可绘制的实体(精灵、文本、形状、顶点数组或您自己的可绘制实体)。

// the abstract base class
class Node
{
public:

    // ... functions to transform the node

    // ... functions to manage the node's children

    void draw(sf::RenderTarget& target, const sf::Transform& parentTransform) const
    {
        // combine the parent transform with the node's one
        sf::Transform combinedTransform = parentTransform * m_transform;

        // let the node draw itself
        onDraw(target, combinedTransform);

        // draw its children
        for (std::size_t i = 0; i < m_children.size(); ++i)
            m_children[i]->draw(target, combinedTransform);
    }

private:

    virtual void onDraw(sf::RenderTarget& target, const sf::Transform& transform) const = 0;

    sf::Transform m_transform;
    std::vector<Node*> m_children;
};

// a simple derived class: a node that draws a sprite
class SpriteNode : public Node
{
public:

    // .. functions to define the sprite

private:

    virtual void onDraw(sf::RenderTarget& target, const sf::Transform& transform) const
    {
        target.draw(m_sprite, transform);
    }

    sf::Sprite m_sprite;
};
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
探索全栈前端技术的魅力:HTML+CSS+JS+JQ+Bootstrap网站源码深度解析 在这个数字化时代,构建一个既美观又功能强大的网站成为了许多开发者和企业追逐的目标。本份资源精心汇集了一套完整网站源码,融合了HTML的骨架搭建、CSS的视觉美化、JavaScript的交互逻辑、jQuery的高效操作以及Bootstrap的响应式设计,全方位揭秘了现代网页开发的精髓。 HTML,作为网页的基础,它构建了信息的框架;CSS则赋予网页生动的外观,让设计创意跃然屏上;JavaScript的加入,使网站拥有了灵动的交互体验;jQuery,作为JavaScript的强力辅助,简化了DOM操作与事件处理,让编码更为高效;而Bootstrap的融入,则确保了网站在不同设备上的完美呈现,响应式设计让访问无界限。 通过这份源码,你将: 学习如何高效组织HTML结构,提升页面加载速度与SEO友好度; 掌握CSS高级技巧,如Flexbox与Grid布局,打造适应各种屏幕的视觉盛宴; 理解JavaScript核心概念,动手实现动画、表单验证等动态效果; 利用jQuery插件快速增强用户体验,实现滑动效果、Ajax请求等; 深入Bootstrap框架,掌握移动优先的开发策略,响应式设计信手拈来。 无论是前端开发新手渴望系统学习,还是资深开发者寻求灵感与实用技巧,这份资源都是不可多得的宝藏。立即深入了解,开启你的全栈前端探索之旅,让每一个网页都成为技术与艺术的完美融合!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值