大家好,今天是用法系列(话说这跟用法有关系吗......)的第n+m期,今天我们初步了解一下sfml
1.介绍
sfml全名叫Simple and Fast Multimedia Library,是一个基于c++开发的2维多媒体库,用于开发简易游戏或多媒体应用程序,创于2007年8月9日,基于sfml团队开发,可以播放音频,绘制图片或图形。
2.导入库
要使用的话,要导入sfml库,因为有些这个库是第三方的,编译器不会自带,只能自行安装下载。
这里可以根据【快速解决】在vs2022中配置SFML图形库_vcpkg安装sfml-CSDN博客 这个帖子下载
3.初步认识
0.使用命名空间
sf是sfml的主要命名空间(好吧其实这个库就一个)这个可写可不写,但要在一些代码前加上"sf::",容易把我们类似,所以必须要加(
using namespace sf;
1.导入窗口
如果你成功导入了,创建一个窗口,可以先创建一个RenderWindow类的对象,并输入一些参数给类中的构造函数,就像这样
RenderWindow window(
VideoMode(800, 600),
"My first Window",
Style::Resize
);
这个构造函数的原型是这样的:
sf::RenderWindow(
sf::VideoMode mode, const std::string& title,
sf::Uint32 style = sf::Style::Default,
const sf::ContextSettings& settings = sf::ContextSettings()
)
第一个是模式,一般输入VideoMode函数编辑长和宽,第二个是标题,第三个是窗口样式,当然他会默认帮你调好样式,有一些其他的样式,比如Style::None是无标题,Style::Titlebar是只显示标题栏,Style::Resize是只能调节窗口大小等
注:如果要起中文名的话请在字符串前加"L",比如"L'标题'"
2.设置帧率
每个游戏都有一个帧率,也就是fps,如果不设置,容易导致运行速度太快而导致cpu使用率太高而容易闪退,那我们就该设置帧率,要设置帧率的话,可以使用RenderWindow::setFramerateLimit函数,就像这样
setFramerateLimit(60);
当然,这里的帧率也可以调整成80,100,120甚至144
3.关闭窗口信息
当然,只创建窗口是不够的,我们还要让他一直保持开启状态,就像这样
while (window.isOpen()){
}
其中的isOpen函数是一个bool类型函数,如果打开,就会返回true,否则会返回false
4.关闭事件
当我们点击关闭按钮时,会发现不会响应,只是因为你没有编辑关闭事件,就像这样
while(window.isOpen()){
Event event;
while(window.pollEvent(event)){
if(event.type == Event::Closed){
window.close();
}
}
其中我们发现我们在程序中创建了Event类的对象,这个类用于获取信息,而pollEvent函数用于处理信息,如果状态是点击关闭按钮,就关闭窗口
这样整个程序代码是这样的
#include <SFML/Graphics.hpp>
int main() {
RenderWindow window(
VideoMode(800, 600),
"My first Window",
Style::Resize
);
window.setFramerateLimit(60);
while (window.isOpen()) {
Event event;
while (window.pollEvent(event)) {
if (event.type == Event::Closed) {
window.close();
}
}
}
return 0;
}
5.设置背景颜色
黑色的窗口似乎不太好看,我们可以把窗口的颜色调成白色,比如
Color backgroundColor = Color::White;
其他颜色也可以,比如淡绿色(144, 238, 144),就可以这么写
Color backgroundColor(144, 238, 144);
只需在后面加上用于刷新的两行就行了
window.clear(backgroundColor); //刷新背景
window.display();
5.绘制图形
我们可以绘制一些简单的图形,比如长方形
RectangleShape square(Vector2f(200.0f, 250.0f)); //长和宽
square.setPosition(Vector2f(100.0f, 100.0f)); //x和y
square.setFillColor(Color::White); //颜色
三角形
sf::ConvexShape triangle; //创建多边形
triangle.setPointCount(3); //设置顶点为三
triangle.setPoint(0, sf::Vector2f(330.0f, 100.0f)); //顶点1坐标
triangle.setPoint(1, sf::Vector2f(530.0f, 100.0f)); //顶点2坐标
triangle.setPoint(2, sf::Vector2f(430.0f, 300.0f)); //顶点3坐标
triangle.setFillColor(Color::White); //设置颜色
圆形
sf::CircleShape circle(60.0f); //半径
circle.setPosition(Vector2f(500.0f,200.0f)); //坐标
circle.setFillColor(Color::White); //颜色
线段
sf::VertexArray line(sf::Lines, 2); //设置线段点为二
line[0].position = Vector2f(100.0f, 100.0f); //线段1坐标
line[0].color = Color::Black; //线段1颜色
line[1].position = Vector2f(300.0f, 300.0f); //线段2坐标
line[1].color = Color::Black; //线段1颜色
顺便提一嘴,这里的坐标是从右下角为(0,0)为中心的
还有文字
sf::Font font; //创建文字对象
std::string fontPath = "comici.TTF"; //导入字体
if (!font.loadFromFile(fontPath)) //如果加载失败,报错
{
std::cerr << "加载失败" << std::endl;
return -1;
}
//创建文本
sf::Text text("安全", font, 40); //设置文本,字体,字号
text.setFillColor(sf::Color::Black); //颜色
text.setPosition(300, 250); //位置
音乐
sf::Music music; //创建音乐对象
if (!music.openFromFile("music.mp3")) //判断加载失败,报错
{
std::cerr << "加载失败!" << std::endl
return -1;
}
music.play(); //播放
music.setVolume(50); //音量
music.setLoop(flase); //是否单曲循环
图片
sf::Texture texture; //图片对象
if (!texture.loadFromFile("image.jpeg")) // 判断加载失败,报错
{
std::cerr << "加载错误" << std::endl;
return -1;
}
sf::Sprite sprite(texture); //创建精灵对象
sprite.setPosition(Vector2f(0, -5)); //位置
字体,图片,音频都需要自行复制到程序目录下
精灵用于绘制图片,最后这些都均可用draw函数绘制,例如刚才的sprite,绘制的方法就是
window.draw(sprite);
6.例子
其实还有一些图形,但太小众,所以不讲,总之我们结合这些,写一个例子
代码:
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace sf; //使用sf命名空间
const int WinWidth = 900; //高
const int WinHeight = 566; //宽
int main() //主函数
{
RenderWindow window(
VideoMode(800, 600), //长和宽
"My first Window", //窗口名
Style::Resize //样式
);
window.setFramerateLimit(60); //设置帧
sf::Texture texture; //创建图片
sf::Font font; //创建字体
Music music;
music.setVolume(50); //音量
music.setLoop(flase); //是否单曲循环
if (!font.loadFromFile("HarmonyOS_Sans_SC_Bold.ttf")) { //如果加载字体失败,报错
std::cerr << "error!" << std::endl;
return -1;
}
if (!texture.loadFromFile("image.jpeg")){ //如果加载图片失败,报错
std::cerr << "加载失败!" << std::endl;
return -1;
}
if(!music.openFromFile("music.mp3")){ //如果加载音乐失败,报错
std::cerr << "加载失败!" << std::endl;
return -1;
}
sf::Sprite sprite(texture); //设置精灵,并继承图片
sprite.setPosition(Vector2f(0, -5)); //设置位置
Text text(L"原来你也玩原神?", font, 50); //设置文本,字体,大小
text.setFillColor(Color::Black); //设置颜色
text.setPosition(Vector2f(20, 20)); //设置文字位置
while (window.isOpen()) //关闭判断
{
Event event;
while (window.pollEvent(event))
{
if (event.type == Event::Closed)
{
window.close();
}
}
window.clear(Color::White); //清除,并设定背景为白
window.draw(sprite); //绘画图片
window.draw(text); //绘制文字
music.play();
window.display(); //刷新
}
system("pause"); //等待
}
运行结果:
(逃到这里应该就没有原批了吧( )
7.图片功能
sfml不仅能绘制图片,还能缩大背景,比如缩大两倍,代码就是这样的
View view;
view.zoom(0.5);
window.setView(view);
也可以移动
View view;
view.move(100, 100);
window.setView(view);
设置窗口大小
window.setSize(sf::Vector2u(1000, 800));
8.其他
我们还发现,代码中有Vector2f和Vector2u字样,这两个类型,一个是保存浮点数的,一个是保存整数,一个常用于坐标或大小,而另一个是测量尺寸,此外还有Vector2i,Vector3i,Vector2f,这个暂且不讲
sfml还可用于3d,需要用到OpenGL,这个也不讲
4.网络
1.服务器
没想到吧,这个库还能用于做服务器,比如实现一个tcp服务器的代码就是这样的
#include <SFML/Network.hpp>
#include <iostream>
int main()
{
sf::TcpListener listener; //创建监听器
if (listener.listen(53000)!= sf::Socket::Done) //如果监听失败,抱错
{
std::cerr << "无法监听端口" << std::endl;
return -1;
}
sf::TcpSocket socket; //创建客户端
if (listener.accept(socket)!= sf::Socket::Done) //如果客户端连接失败,报错
{
std::cerr << "无法接受客户端连接" << std::endl;
return -1;
}
char data[100]; //数据
std::size_t received; //信息大小
if (socket.receive(data, sizeof(data), received)!= sf::Socket::Done) //如果接受数据失败,报错
{
std::cerr << "无法接收数据" << std::endl;
return -1;
}
data[received] = '\0'; //字符串处理
std::cout << "收到客户端消息: " << data << std::endl;
const char response[] = "已收到你的消息";
if (socket.send(response, sizeof(response))!= sf::Socket::Done) //发送信息失败,报错
{
std::cerr << "无法发送响应" << std::endl;
return -1;
}
return 0;
}
2.蓝牙
它还可以连接手柄,比如
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "游戏手柄测试"); //创建窗口
if (sf::Joystick::isConnected(0)) //如果第一个手柄(下标)链接
{
std::cout << "游戏手柄已连接" << std::endl; //输出连接信息
while (window.isOpen()) //关闭判断
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Joystick::isButtonPressed(0, 0)) //如果第一个手柄按下0按钮
{
std::cout << "手柄按钮0被按下" << std::endl; //输出信息
}
window.clear();
window.display();
}
}
else
{
std::cout << "未连接游戏手柄" << std::endl; //否则连接失败
}
return 0;
}