介绍
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);
请记住,消除锯齿的可用性取决于图形卡:它可能不支持,或在驱动程序设置中被强制禁用。