尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

SFML3.0 教程

SFML3.0 教程
📅 发布时间:2026/6/19 21:17:01

SFML2和SFML3区别

没有学过SFML的请跳过此章节。
这里写的是SFML2到SFML3一些比较突出的变化,还有一些没有说到。

编译器

SFML3的c++标准现在提高到了c++17,编译的时候需要使用-std=c++17选项。
同时需要升级你的编译器版本。

编译器 版本
MSVC 16(VS2019)
GCC 9
Clang 9
AppleClang 12

MSVC编译器是VS2019的版本,一般都没有问题。
可以在终端使用 g++/clang++ -v来检查版本。

tan_zhixia@tanzhixiadeMac-mini luogu % clang++ -v
Apple clang version 17.0.0 (clang-1700.6.3.2)
Target: arm64-apple-darwin25.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Vector

在SFML3中,函数中的位置坐标换成了一个Vector(注意不是STL的vector),需要把SFML2的x, y用大括号包起来。
看不懂没关系,看一下代码就懂了。
SFML2

sf::VideoMode videoMode(480, 640, 24);
sf::CircleShape circle(10);
circle.setPosition(10, 20);
sf::IntRect rect(250, 400, 50, 100);

SFML3

sf::VideoMode videoMode({480, 640}, 24);
sf::CircleShape circle(10);
circle.setPosition({10, 20});
sf::IntRect rect({250, 400}, {50, 100});

事件处理

SFML3使用了类型安全的事件处理方式,一开始我用SFML3的时候一直报错,后来发现Event的默认构造函数被删除了。

SFML2使用以下事件处理模板。

sf::Event event;
while (window.pollEvent(event)) {if (event.type == sf::Event::Closed)window.close();
}

SFML3改变了,使用了这个模板

while (std::optional<sf::Event> event = window.pollEvent()) {if (event->is<sf::Event::Closed>()) {window.close();}
}

如果需要迁移项目,要把event.type == ?改成event->is<?>()或者event->getIf<?>()。

SFML教程

配置教程

Windows

Windows系统使用vs2022进行配置,配置方法和SFML2差不多。这里贴出CSDN上面的一个SFML2的配置

Macos

Macos系统用brew下载SFML和make。

brew install sfml
brew install make

下载完成之后,找到SFML的安装路径(有可能在/opt/homebrew/opt,每个电脑的情况不一样),配置cmake。

list(APPEND CMAKE_PREFIX_PATH "/opt/homebrew/opt")
find_package(SFML 3 COMPONENTS Graphics Window System Audio Network REQUIRED)
target_link_libraries(main PRIVATESFML::GraphicsSFML::WindowSFML::SystemSFML::AudioSFML::Network
)

cmake的其他配置就不用说了吧。

窗口

SFML中的Windows由sf::Window类定义。

#include <SFML/Window.hpp>int main() {sf::Window window(sf::VideoMode({800, 600}), "My window");...
}

窗口参数

VideoMode

VideoMode表示的是窗口的大小,比如sf::Window window(sf::VideoMode({800, 600}), "My window");就是一个大小为(800, 600)的窗口。
里面一般会塞一个Vector2u,但是可以简写成{x, y}的形式。

标题

第二个参数是窗口的标题

样式

第三个参数是可选参数,表示窗口的样式

样式 描述
sf::Style::None 根本没有装饰
sf::Style::Titlebar 窗口有一个标题栏
sf::Style::Resize 窗口可以调整大小,并有一个最大化按钮
sf::Style::Close 窗口有一个关闭按钮
sf::Style::Default 默认样式,是Titlebar | Resize | Close

全屏窗口

第四个参数可以定义是普通窗口还是全屏的

状态 描述
sf::State::Windowed 普通窗口
sf::State::Fullscreen 全屏窗口

第五个参数

第五个参数是关于OpenGL的,现在用不到。

注意事项

在Mac上,你不能在主线程之外的其他地方使用窗口和绘图。
在Windows上,你不能打开一个比屏幕还大的窗口。
Window不能绘图,但是是作为RenderWindow的前置知识。

事件处理

#include <SFML/Window.hpp>int main() {sf::Window window(sf::VideoMode({800, 600}), "My window");...
}

这是我们的程序,如果不在...的位置写入任何程序,窗口就会闪退,就算加一个 while (true) {},窗口也会卡死。
所以我们要使用事件处理来处理事件。

主循环

在...的位置添加一个这样的while循环。

while (window.isOpen()) {...
}

事件循环

我们在主循环的...再添加一个while循环用来处理事件。

while (std::optional<sf::Event> event = window.pollEvent()) {if (event->is<sf::Event::Closed>()) {window.close();}
}

这次复杂了好多,来一个一个来说它们的意思。
std::optional是一个STL中的一个容器,表示可以是无这种状态,std::optionalsf::Event就表示这个事件有可能是没有。
window.pollEvent()是Window的一个方法,用来返回事件信息。
里面的if虽然看不懂,但是你应该也能猜到它的意思:如果事件是sf::Event::Closed,那么就把窗口关了。然后window.isOpen()返回false主循环结束,返回0。

事件

关闭事件

使用event->is<sf::Event::Closed>()判断,这是最常用的事件,接收到这个事件,应该关闭窗口,清理数据。

窗口调整大小事件

当窗口被我们拉伸,全屏,最大化后或者使用编程方式改变大小就会触发这个事件。
使用event->getIf<sf::Event::Resized>()判断,这个函数返回一个resized后的窗口信息,可以用变量接收它。

if (const auto* resized = event->getIf<sf::Event::Resized>()) {std::cout << "new width: " << resized->size.x << std::endl;std::cout << "new height: " << resized->size.y << std::endl;
}
键盘事件

当键盘按下或松开的时候会触发KeyPressed或KeyReleased事件。
两个都使用event->getIf<事件>()判断并且可以用变量接收。
变量里面存着按键信息。

if (const auto* keyPressed = event->getIf<sf::Event::KeyPressed>()) {if (keyPressed->scancode == sf::Keyboard::Scan::Escape) {std::cout << "the escape key was pressed" << std::endl;std::cout << "scancode: " << static_cast<int>(keyPressed->scancode) << std::endl;std::cout << "code: " << static_cast<int>(keyPressed->code) << std::endl;std::cout << "control: " << keyPressed->control << std::endl;std::cout << "alt: " << keyPressed->alt << std::endl;std::cout << "shift: " << keyPressed->shift << std::endl;std::cout << "system: " << keyPressed->system << std::endl;std::cout << "description: " << sf::Keyboard::getDescription(keyPressed->scancode).toAnsiString() << std::endl;std::cout << "localize: " << static_cast<int>(sf::Keyboard::localize(keyPressed->scancode)) << std::endl;std::cout << "delocalize: " << static_cast<int>(sf::Keyboard::delocalize(keyPressed->code)) << std::endl;}
}
鼠标事件

在鼠标按下或松开的时候会触发MouseButtonPressed或MouseButtonReleased事件。
两个都使用event->getIf<事件>()判断并且可以用变量接收。
变量里面存着鼠标按键信息。

if (const auto* mouseButtonPressed = event->getIf<sf::Event::MouseButtonPressed>()) {if (mouseButtonPressed->button == sf::Mouse::Button::Right) {std::cout << "the right button was pressed" << std::endl;std::cout << "mouse x: " << mouseButtonPressed->position.x << std::endl;std::cout << "mouse y: " << mouseButtonPressed->position.y << std::endl;}
}

绘图

想要绘图,我们就要把Window改成RenderWindow(Window没有绘图功能),同时还要把头文件改成<SFML/Graphics.hpp>。
我们先贴一下代码

#include <SFML/Graphics.hpp>
#include <optional>
int main() {sf::RenderWindow window(sf::VideoMode({800, 600}), "SFML Window");while (window.isOpen()) {while (std::optional<sf::Event> event = window.pollEvent()) {if (event->is<sf::Event::Closed>()) {window.close();}}window.clear(sf::Color::White);window.display();}return 0;
}

首先你应该注意到的是多出来的window.clear(sf::Color::White);和window.display();(其他的讲过啦)。
我们一个一个讲

window.clear()

window.clear()函数用于清空窗口,默认会使用黑色填充,可以在大括号内设置颜色。sf::Color::White表示白色。
sf::Color的颜色介绍一下最基础的,反正要么用纹理要么用RGB。

颜色 代码
黑色 sf::Color::Black
白色 sf::Color::White
红色 sf::Color::Red
绿色 sf::Color::Green
蓝色 sf::Color::Blue
透明 sf::Color::Transparent

我翻了一下Color的构造函数,可以使用sf::Color(r, g, b)和sf::Color(r, g, b, a)来自定义颜色,还是挺灵活的。
有兴趣的读者可以把window.clear(sf::Color::White);换成window.clear(sf::Color(20, 100, 40));看看是什么颜色的。

window.display()

就是很简单的一个逻辑,你绘制的东西不会直接显示出来,而是放到缓冲区里,调用这个函数就是把缓冲区的显示出来,不信可以注释掉它。

图形

最最最基础的讲完了,我们讲一讲最最基础的——图形。
图形一般都会有一些通用的方法让我们调用,你甚至可以创建自己的图形类,但是要实现这些函数。

颜色

刚讲过,忘了么sf::Color?

轮廓

形状会有一个轮廓,自己复制这段代码测试。(在clear和display中间,不用我提醒吧)

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));window.draw(shape);

注:sf::CircleShape shape(50.f);是一个
轮廓默认是向外扩展的,所以会变大,如果不想这样可以设置shape.setOutlineThickness(-10.f);变成负的,这样就向内扩张了。

种类

因为这是一个基础教程,也不能讲太复杂,所以就简单讲一讲。

图形 类 参数
圆形 sf::CircleShape 半径
矩形 sf::RectangleShape {长+宽}大括号包起来
正多边形 sf::CircleShape 半径 边数

之所以正多边形是sf::CircleShape是因为圆形也是一种正多变形(默认给的是200边形,很接近圆),第二个参数指定的是圆的精细度,默认是200。官方文档也说明是这样创建的

精灵与纹理

纹理

纹理可以上传本地图片,使用sf::Texture texture("image.png");来创建一个纹理。
纹理的另一种定义方式是直接sf::Texture texture;创建空纹理。
然后使用texture.loadFromFile()来导入和处理错误。

// load a 32x32 rectangle that starts at (10, 10)
sf::Texture texture("image.png"); // Throws sf::Exception if an error occurs// ORsf::Texture texture;
if (!texture.loadFromFile("image.png") {// error...
}

精灵

精灵创建很简单,直接使用sf::Sprite sprite(texture);就行了,注意sprite没有默认构造函数,每个精灵都会绑定一个texture。
精灵创建开销很小,一般来说用于绘制纹理。
如果你愿意的话我会把我以前写的纹理管理器和精灵管理器发布。
哦对了,没有讲完,最后用window.draw(sprite)绘制它,完美。
(我看文档的时候因为sprite有雪碧的意思,翻译软件翻译成了好的,我现在能吃我的雪碧吗?)

结束

好了,这就是本教程的全部内容,毕竟是第一篇博客,所以有没讲到的地方请大家评论。
最后贴出官方文档的地址
欢迎大家补充!

相关新闻

  • Springboot家政服务管理系统w6nqa(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • recv和send(及与read、write的区别)
  • WSL中开发UI程序

最新新闻

  • 红队内网渗透利器,告别原版特征暴露(支持免杀)内网扫描爆破后渗透一站式落地
  • 2026体系认证哪家通过率高?关键选择因素解析 - 品牌排行榜
  • 芯片数据手册修订历史深度解析:从MPC5676R看硬件设计关键要点
  • 从零到一:使用PowerDesigner构建高效数据库物理模型
  • AI在生物学研究中的真实能力边界与辅助实践
  • LPC43S70 ADC信号完整性优化:从引脚串扰到输入电路设计

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号