SFML2.6 图形模块--形状

介绍

SFML提供了一组表示简单形状实体的类。每种形状都是一个独立的类,但它们都继承自相同的基类,以便它们可以访问相同的共同特征的子集。然后,每个类都会添加自己的特定属性:圆形类的半径属性,矩形类的尺寸属性,多边形类的点属性等。

常用形状属性

变换(位置、旋转、缩放)

这些属性是SFML图形类的共同属性,因此它们在一个单独的教程中进行解释:转换实体

颜色

形状的基本属性之一是它的颜色。您可以使用setFillColor函数更改颜色。

sf::CircleShape shape(50.f);

// set the shape color to green
shape.setFillColor(sf::Color(100, 250, 50));

在这里插入图片描述

轮廓线

形状可以有轮廓线。您可以使用setOutlineThickness和setOutlineColor函数设置轮廓线的粗细和颜色。

sf::CircleShape shape(50.f);
shape.setFillColor(sf::Color(150, 50, 250));

// set a 10-pixel wide orange outline
shape.setOutlineThickness(10.f);
shape.setOutlineColor(sf::Color(250, 150, 100));

在这里插入图片描述
默认情况下,轮廓线向外延伸出形状(例如,如果您有一个半径为10且轮廓线厚度为5的圆形,则圆形的总半径为15)。您可以通过设置负的厚度使其向形状的中心延伸。

要禁用轮廓线,请将其厚度设置为0。如果您只想要轮廓线,则可以将填充颜色设置为sf::Color::Transparent。

纹理

形状也可以像精灵一样纹理化。要指定要映射到形状的部分纹理,必须使用setTextureRect函数。它接受要映射到形状边界矩形的纹理矩形。这种方法虽然不提供最大的灵活性,但比单独设置每个形状点的纹理坐标要容易得多。

sf::CircleShape shape(50);

// map a 100x100 textured rectangle to the shape
shape.setTexture(&texture); // texture is a sf::Texture
shape.setTextureRect(sf::IntRect(10, 10, 100, 100));

在这里插入图片描述
请注意,轮廓不纹理化。

重要的是要知道,纹理与形状的填充颜色相乘。如果填充颜色为sf::Color::White,则纹理将显示为未经修改的状态。要禁用纹理,调用setTexture(NULL)。

绘制形状

绘制形状与绘制任何其他SFML实体一样简单:

window.draw(shape);

内置形状类型

矩形

要绘制矩形,可以使用sf::RectangleShape类。它只有一个属性:矩形的大小。

// define a 120x50 rectangle
sf::RectangleShape rectangle(sf::Vector2f(120.f, 50.f));

// change the size to 100x100
rectangle.setSize(sf::Vector2f(100.f, 100.f));

在这里插入图片描述

圆由sf::CircleShape类表示。它有两个属性:半径和边数。边数是一个可选属性,它允许您调整圆的“质量”:圆必须由许多边形近似(图形卡无法直接绘制完美的圆),并且此属性定义了您圆形近似将具有多少个边。如果您绘制小圆,则可能只需要几个边。如果您绘制大圆或放大常规圆,则很可能需要更多的边。

// define a circle with radius = 200
sf::CircleShape circle(200.f);

// change the radius to 40
circle.setRadius(40.f);

// change the number of sides (points) to 100
circle.setPointCount(100);

在这里插入图片描述

常规多边形

实际上,没有专门用于正多边形的类,事实上,您可以使用sf :: CircleShape类表示具有任意数量边的正多边形:由于圆由许多边的多边形近似,因此您只需要玩转边数即可获得所需的多边形。一个具有3个点的sf::CircleShape是一个三角形,具有4个点是正方形,以此类推。

// define a triangle
sf::CircleShape triangle(80.f, 3);

// define a square
sf::CircleShape square(80.f, 4);

// define an octagon
sf::CircleShape octagon(80.f, 8);

在这里插入图片描述

凸多边形形状

sf::ConvexShape类是最终的形状类:它允许您定义任何凸多边形形状。SFML无法绘制凹多边形形状。如果您需要绘制凹多边形形状,则必须将其拆分为多个凸多边形。

要构造凸形状,您必须首先设置它应该具有的点数,然后定义这些点。

// create an empty shape
sf::ConvexShape convex;

// resize it to 5 points
convex.setPointCount(5);

// define the points
convex.setPoint(0, sf::Vector2f(0.f, 0.f));
convex.setPoint(1, sf::Vector2f(150.f, 10.f));
convex.setPoint(2, sf::Vector2f(120.f, 90.f));
convex.setPoint(3, sf::Vector2f(30.f, 100.f));
convex.setPoint(4, sf::Vector2f(0.f, 50.f));

定义点的顺序非常重要。它们必须全部按顺时针或逆时针的顺序定义。如果您以不一致的顺序定义它们,形状将被错误地构造。

在这里插入图片描述
尽管 sf::ConvexShape 的名称暗示它只应用于表示凸多边形,但它的要求却更加宽松。事实上,您的形状必须满足的唯一要求是如果您从其重心向所有点绘制线条,则这些线条必须按相同顺序绘制。您不能“跳过先前的线条”。在内部,凸多边形是使用三角形扇自动构造的,如果您的形状可以用三角形扇表示,那么您可以使用 sf::ConvexShape。基于这个宽松的定义,例如,您可以使用 sf::ConvexShape 绘制星形。

线

SFML 中没有专门用来表示线的形状类。原因很简单:如果您的线有厚度,它就是一个矩形。如果没有厚度,它可以用线条原始图元绘制。

如果要绘制带有厚度的线条:

sf::RectangleShape line(sf::Vector2f(150.f, 5.f));
line.rotate(45.f);

在这里插入图片描述
没有厚度的线条

sf::Vertex line[] =
{
    sf::Vertex(sf::Vector2f(10.f, 10.f)),
    sf::Vertex(sf::Vector2f(150.f, 150.f))
};

window.draw(line, 2, sf::Lines);

在这里插入图片描述
要了解更多关于顶点和图元的知识,您可以阅读有关顶点数组的教程。

自定义形状类型

您可以使用自己的形状类型扩展形状类的集合。为此,您必须从sf::Shape派生并覆盖两个函数:

  • getPointCount: 返回形状中点的数量
  • getPoint: 返回形状的一个点

每当您形状中的任何点发生更改时,您还必须调用update()保护函数,以便通知基类并更新其内部几何图形。

下面是一个完整的自定义形状类EllipseShape的示例:

class EllipseShape : public sf::Shape
{
public :

    explicit EllipseShape(const sf::Vector2f& radius = sf::Vector2f(0.f, 0.f)) :
    m_radius(radius)
    {
        update();
    }

    void setRadius(const sf::Vector2f& radius)
    {
        m_radius = radius;
        update();
    }

    const sf::Vector2f& getRadius() const
    {
        return m_radius;
    }

    virtual std::size_t getPointCount() const
    {
        return 30; // fixed, but could be an attribute of the class if needed
    }

    virtual sf::Vector2f getPoint(std::size_t index) const
    {
        static const float pi = 3.141592654f;

        float angle = index * 2 * pi / getPointCount() - pi / 2;
        float x = std::cos(angle) * m_radius.x;
        float y = std::sin(angle) * m_radius.y;

        return sf::Vector2f(m_radius.x + x, m_radius.y + y);
    }

private :

    sf::Vector2f m_radius;
};

在这里插入图片描述

抗锯齿形状

没有选项可以消除单个形状的锯齿。要获得消除锯齿的形状(即具有平滑边缘的形状),必须在创建窗口时全局启用反锯齿,使用sf::ContextSettings结构的相应属性。

sf::ContextSettings settings;
settings.antialiasingLevel = 8;

sf::RenderWindow window(sf::VideoMode(800, 600), "SFML shapes", sf::Style::Default, settings);

在这里插入图片描述
请记住,消除锯齿的可用性取决于图形卡:它可能不支持,或在驱动程序设置中被强制禁用。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面我会给你讲解如何使用SFML来实现n-puzzle游戏的可视化。首先,我们需要了解一下SFML是什么。 SFML是一个跨平台的图形库,它提供了简单易用的API,可以帮助我们快速创建2D游戏和图形应用程序。它支持多种编程语言,包括C++、Python、Java等。 接下来,我们可以开始实现n-puzzle游戏的可视化了。首先,我们需要创建一个窗口来显示游戏界面。以下是创建窗口的代码: ```cpp #include <SFML/Graphics.hpp> int main() { sf::RenderWindow window(sf::VideoMode(800, 600), "N-Puzzle Game"); while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); } window.clear(sf::Color::White); // 绘制游戏界面 window.display(); } return 0; } ``` 这段代码创建了一个800x600大小的窗口,并且在每一帧中都会清空窗口并绘制游戏界面。接下来,我们需要实现游戏界面的绘制。 n-puzzle游戏的界面由一个N*N的网格组成,每个格子中都会有一个数字。我们可以使用SFML中的矩形来表示每个格子,并且使用文本来显示数字。以下是绘制游戏界面的代码: ```cpp const int N = 3; const int tileSize = 100; sf::RectangleShape tile(sf::Vector2f(tileSize, tileSize)); tile.setFillColor(sf::Color::White); tile.setOutlineColor(sf::Color::Black); tile.setOutlineThickness(2); sf::Font font; font.loadFromFile("arial.ttf"); sf::Text text("", font, tileSize / 2); text.setFillColor(sf::Color::Black); text.setStyle(sf::Text::Bold); text.setOrigin(text.getGlobalBounds().width / 2, text.getGlobalBounds().height / 2); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { int number = i * N + j + 1; if (number == N * N) continue; tile.setPosition(j * tileSize, i * tileSize); text.setString(std::to_string(number)); text.setPosition(j * tileSize + tileSize / 2, i * tileSize + tileSize / 2); window.draw(tile); window.draw(text); } } ``` 这段代码首先定义了每个格子的大小为100x100,并且使用白色填充和黑色边框。然后,它加载了一个字体文件,并且创建了一个文本对象来显示数字。最后,它使用两个嵌套循环来绘制整个游戏界面。 这样,我们就完成了n-puzzle游戏的可视化。完整代码如下: ```cpp #include <SFML/Graphics.hpp> const int N = 3; const int tileSize = 100; int main() { sf::RenderWindow window(sf::VideoMode(N * tileSize, N * tileSize), "N-Puzzle Game"); sf::RectangleShape tile(sf::Vector2f(tileSize, tileSize)); tile.setFillColor(sf::Color::White); tile.setOutlineColor(sf::Color::Black); tile.setOutlineThickness(2); sf::Font font; font.loadFromFile("arial.ttf"); sf::Text text("", font, tileSize / 2); text.setFillColor(sf::Color::Black); text.setStyle(sf::Text::Bold); text.setOrigin(text.getGlobalBounds().width / 2, text.getGlobalBounds().height / 2); while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); } window.clear(sf::Color::White); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { int number = i * N + j + 1; if (number == N * N) continue; tile.setPosition(j * tileSize, i * tileSize); text.setString(std::to_string(number)); text.setPosition(j * tileSize + tileSize / 2, i * tileSize + tileSize / 2); window.draw(tile); window.draw(text); } } window.display(); } return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值