当前位置: 首页 > news >正文

SFML3.0 教程

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有雪碧的意思,翻译软件翻译成了好的,我现在能吃我的雪碧吗?

结束

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

http://www.jsqmd.com/news/150022/

相关文章:

  • 基于知识图谱的AI Agent推理系统
  • recv和send(及与read、write的区别)
  • 社交媒体话题热度预测:公关策略制定依据
  • WSL中开发UI程序
  • 特殊教育辅助系统:包容性社会的技术体现
  • 环保公益项目评估AI:社会效益量化新方式
  • 异常登录行为检测:账户安全的隐形卫士
  • 转义字符.
  • 2025空压机厂家top5榜单 - 栗子测评
  • NVIDIA官方推荐:TensorRT如何重塑深度学习推理生态
  • 杭州五七望乡台,搭棚服务厂家哪家好 - 栗子测评
  • 2025彩钢瓦除锈喷漆工艺哪家好?厂家综合实力榜单 - 栗子测评
  • 2025拉伸件生产厂家排行榜重金属拉伸件厂家怎么选 - 栗子测评
  • 2025精密激光切割机选哪家?这篇告诉你激光设备哪家好 - 栗子测评
  • 2025kbk轨道生产厂家:kbk铝合金轨道起重机哪个牌子好 - 栗子测评
  • 疫苗接种点智能调度:资源分配最优化方案
  • 苍穹外卖——DAY5
  • 2025最新!自考党必看!8个AI论文工具深度测评与推荐
  • ‌测试数据即服务:解决数据依赖与隐私合规的创新方案‌
  • 2025杭州民办高中排名更新!杭州哪些高中招体育生大盘点 - 栗子测评
  • 2025kbk刚性轨道起重机推荐厂家:kbk起重机厂家哪家好 - 栗子测评
  • 用户投诉自动分类系统:客户服务效率倍增
  • 留学申请文书生成服务:个性化内容快速产出
  • 2025输送机厂家排行榜 - 栗子测评
  • 杭州专业殡仪服务公司推荐 2025杭州专业殡仪服务公司权威 - 栗子测评
  • 虚假信息传播路径追踪:社会治理的AI视角
  • 微高压氧舱代理加盟哪家好?2025微高压氧舱加盟推荐大盘点 - 栗子测评
  • 2025隔膜泵配件膜片哪家好?气动隔膜泵厂家推荐榜 - 栗子测评
  • 口碑好的杭州寿衣公司推荐 2025杭州寿衣公司哪家好 - 栗子测评
  • 【EMG肌电信号】基于matlab DWT和EMD技术去噪肌电图信号的性能研究【含Matlab源码 14788期】