SFML2.6 图形模块--文本和字体

加载字体

在绘制文本之前,您需要有可用的字体,就像任何其他打印文本的程序一样。字体封装在sf::Font类中,提供了三个主要功能:加载字体、从中获取字形(即可视化字符)以及读取其属性。在典型的程序中,您只需要利用第一个功能,即加载字体,让我们先关注这个。

加载字体的最常见方式是从磁盘上的文件中,这是通过loadFromFile函数完成的。

sf::Font font;
if (!font.loadFromFile("arial.ttf"))
{
    // error...
}

请注意,SFML不会自动加载您的系统字体,即font.loadFromFile(“Courier New”)不起作用。首先,因为SFML需要文件名,而不是字体名称;其次,因为SFML没有魔法去访问您的系统字体文件夹。如果您想加载字体,您需要将字体文件包含在应用程序中,就像其他所有资源(图像、声音等)一样。

loadFromFile函数有时会在没有明显原因的情况下失败。首先,请检查SFML打印到标准输出的错误消息(请检查控制台)。如果消息是"unable to open file",请确保工作目录(即任何文件路径都相对解释的目录)是您认为的那个:当您从桌面环境运行应用程序时,工作目录是可执行文件夹。(但是,当您从IDE(Visual Studio、Code::Blocks等)启动程序时,工作目录有时可能设置为项目目录。在项目设置中通常可以很容易地更改此设置。)

您还可以从内存(loadFromMemory)或自定义输入流(loadFromStream)加载字体文件。

SFML支持大多数常见的字体格式。完整列表可在API文档中查看。

这就是您需要做的全部。一旦字体加载完毕,您就可以开始绘制文本。

绘制文本

要绘制文本,您将使用sf:: text类。使用起来非常简单:

sf::Text text;

// select the font
text.setFont(font); // font is a sf::Font

// set the string to display
text.setString("Hello world");

// set the character size
text.setCharacterSize(24); // in pixels, not points!

// set the color
text.setFillColor(sf::Color::Red);

// set the text style
text.setStyle(sf::Text::Bold | sf::Text::Underlined);

...

// inside the main loop, between window.clear() and window.display()
window.draw(text);

在这里插入图片描述
文本也可以进行变换:它们具有位置、方向和缩放。涉及到的函数与sf::Sprite类和其他SFML实体相同。这些函数在“变换实体”教程中进行了说明。

如何避免非ascii字符的问题?

处理非ASCII字符(例如带重音符号的欧洲字符、阿拉伯字符或中文字符)可能比较棘手。这需要对解释和绘制文本涉及的各种编码有很好的理解。为了避免处理这些编码,有一个简单的解决方案:使用宽字面字符串。

text.setString(L"יטאח");

只需在字符串前添加“L”前缀就可让它工作,这个前缀告诉编译器生成一个宽字符串。在C++中,宽字符串是一种奇怪的类型:标准并没有说明它们的大小(16位?32位?),也没有说明它们使用的编码(UTF-16?UTF-32?)。不过,我们知道,在大多数平台上,它们都将生成Unicode字符串,并且SFML知道如何正确处理它们。

需要注意的是,C++11标准支持使用新的字符类型和前缀来构建UTF-8、UTF-16和UTF-32字符串字面量,但SFML尚未支持它们。

显而易见的是,您还必须确保所使用的字体包含您要绘制的字符。事实上,字体并不包含所有可能的字符的字形(Unicode标准有超过100,000个字符!),例如,一个阿拉伯字体将无法显示日语文本。

创建自己的文本类

如果 sf::Text 太受限,或者您想对预渲染的字形做其他事情,那么 sf::Font 提供了您需要的一切。

您可以检索一个特定大小的纹理,其中包含所有预渲染的字形:

const sf::Texture& texture = font.getTexture(characterSize);

需要注意的是,当请求字形时,它们才会被添加到纹理中。有这么多字符(记住,超过100000),当你加载字体时,它们不能全部生成。相反,当您调用 getGlyph 函数时,它们会在运行时动态渲染。

如果要对字体纹理进行有意义的操作,则必须获取其中包含的字形的纹理坐标:

sf::Glyph glyph = font.getGlyph(character, characterSize, bold);

其中,character 是要获取字形的字符的 UTF-32 代码。还必须指定字符大小,以及要使用粗体或常规版本的字形。

sf::Glyph 结构包含三个成员:

  • textureRect 包含字形在纹理中的纹理坐标
  • bounds 包含字形的边界矩形,有助于将其相对于文本的基线定位
  • advance 是要应用的水平偏移量,以获取文本中下一个字形的起始位置

你还可以获取字体的其他一些指标,比如两个字符之间的紧缩度或者行间距(总是针对某个字符大小):

int lineSpacing = font.getLineSpacing(characterSize);

int kerning = font.getKerning(character1, character2, characterSize);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值