目录
Disabling the mouse cursor (禁用鼠标光标)
Shape rendering and transformations (形状的渲染和转换)
创建窗口
当你开始开发一款游戏时,你可能想做的第一件事便是打开一扇窗口。在SFML中,这再容易不过了。创建窗口只需要一行代码:
#include <SFML/Graphics.hpp>
int main()
{
sf::Window window(sf::VideoMode(200, 200), "HUANGCHENGTAO!"); //创建窗口代码
sf::sleep(sf::seconds(3)); //添加此代码 这样我们就可以创建窗口之后,运行代码可以看到窗口,否则不可以
return 0;
}
● main函数唯一做的是通过调用sf :: Window构造函数初始化窗口变量,之后程序退出。 还可以使用默认构造函数打开一个窗口,然后调用window::create() 该函数,这个函数的参数与构造函数的参数完全相同。如果在已经打开的窗口上调用Window::create ( ),它会关闭窗口并用新的一组参数重新初始化该窗口。
● 请注意 Window 和VideoMode 都在sf命名空间中。SFML中的每个类都位于该命名空间之下,该命名空间将SFML中的所有类与其他库中的类区分开。
如果我们运行示例中的代码,就不会看到太多内容。程序在创建窗口后立即退出。这是因为我们只是创建了一个窗口,而没有对它做任何操作,程序在main ( )方法结束后自然退出。事实上,我们创建了一个窗口,这并不意味着它可以完全正常工作(至少现在还没有)。我们必须根据我们想要它做的事情来对它进行编程。现在,让我们通过延迟窗口的线程来阻止main函数完成。SFML为此提供了一个简单的接口;只需在创建窗口的行之后添加sf::sleep(sf::seconds(3))。现在,窗口在睡眠期间是清晰可见的。
● 我们可以在创建窗口时指定各种配置—— window size, title, style, and graphics settings. 您可能已经注意到我们将两个参数传递 给 Window构造函数 -—— 一个VideoMode实例和一个字符串(标题)。 构造函数实际上最多可以使用四个参数,最后两个是可选的 - Style 和ContextSettings。下一部分将介绍这些参数的含义以及如何使用它们。
VideoMode
● VideoMode类包含显示一个窗口的信息,例如:width, height, and bits per pixel. 最后一个参数是表示每个像素颜色的位数。它的默认值为32,如果我们想要创建一个全屏窗口,所提供的值必须由机器的显示器和显卡支持。如果我们为全屏窗口选择无效的参数,窗口创建将会失败的。可以使用 VideoMode:: isValid() 方法检 查VideoMode 类的有效性,结果返回一个布尔值。
● 如果我们需要根据桌面的大小 (or the pixel depth) 创建窗口,VideoMode::getDesktopMode()是一个静态方法。另一方面,如果我们要在全屏模式下创建一个窗口,我们可能需要使用 VideoMode::getFullScreenModes() 检查可用的分辨率。这将返回video modes 的std::vector,我们可以自己选择其中一种模式,或者让用户决定哪种模式最适合他们。
然而,仅仅指定全屏的VideoMode 还不足以创建全屏窗口。我们也需要设定一个窗口的Style。
Style
● Style参数是一个bit mask 。mask 是 flags 的组合,其中每个flags代表mask 的一个特定位。 在这种情况下,flags存储在 sf::Style 名称空间中的enum中。我们可以使用flags 的组合来创建所需的标志掩码。以下是SFML提供的Styles:
Enum value | 描述 |
sf::Style ::None | 这个窗户没有任何装饰,也不能与任何其它的Style 一起使用 |
sf::Style ::Titlebar | 添加一个标题栏 |
sf::Style ::Resize | 这增加了一个最大化按钮。还允许手动调整窗口的大小 |
sf::Style ::Close | 添加一个关闭按钮 |
sf::Style ::Fullscreen | 这将以全屏的形式打开窗口。 请注意,这不能与任何其他样式结合使用并且需要有效的VideoMode |
sf::Style ::Default | 这将标题栏、大小调整和关闭组合在一起。这是默认样式。 |
可以通过使用位运算符来组合不同的样式。如果我们想要一个带有标题栏和关闭按钮的窗口,我们可以这样写:
sf::Uint32 style = sf::Style::Titlebar | sf::Style::Close;
这里要做的唯一一件事就是将该样式作为Window构造函数的第三个参数传递。
ContextSettings
● 最后一个参数是ContextSettings的一个实例。 它们构成是一组设置的集合,描述了所需的rendering context. SFML使用OpenGL进行底层渲染,因此这些设置与它直接相关。 可用的context设置如下:
- depthBits ——这指的是深度缓冲区位数。
- stencilBits —— 这指的是模板缓冲区的位数。
- antialiasingLevel: —— 这引用了所请求的多重采样级别数 multisampling levels number .
- majorVersion and minorVersion: —— 这些是指所要求的OpenGL版本
这些设置中的每一个都将在第5章(操作2D摄像机)中得到更详细的解释,您将学习如何使用OpenGL直接渲染物体。
Disabling the mouse cursor (禁用鼠标光标)
● Window类有一个方法,可以在窗口上设置光标的可见性 —— Window :: setMouseCursorVisible()。 对于不使用光标的游戏,或者当我们想要将光标的图像更改为与默认情况不同的内容时,这是非常有用的。
The game loop
每个游戏都需要一个循环。这就是它的动力。否则程序就会结束,我们就看不到太多内容了。下面是一个典型的游戏循环:
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(200, 200), "HUANGCHENGTAO!"); //创建窗口代码
sf::sleep(sf::seconds(3)); //这样我们就可以创建窗口之后,运行代码可以看到窗口,否则不可以
while (window.isOpen()) //游戏循环
{
/*
处理输入——处理来自输入设备和窗口的事件。
更新帧——更新场景中的对象
渲染帧 —— 将场景中的对象渲染到窗口上
*/
}
return 0;
}
典型的游戏循环有三个主要阶段:
- 处理输入——处理来自输入设备和窗口的事件。
- 更新帧——更新场景中的对象
- 渲染帧 —— 将场景中的对象渲染到窗口上
SFML中的 Input handling 可以通过捕获事件(由窗口分派的事件)或直接查询输入设备的当前状态来完成。这两种方法有不同的用途。例如,我们可能希望关闭按钮按下事件上的窗口,或者只要按下某个键,就将我们的主角向右移动(直接键查询)。
● 在捕捉和使用事件后,我们到达 update frame 阶段。在这个阶段,我们想要推进我们的游戏逻辑,更新我们的世界状态。 在完成对象 update 之后就是循环的最后一个阶段,我们清除从上次绘制的所有内容,并再次渲染屏幕上的每个对象。
●接下来的阶段是 渲染帧。 在这里,我们清除从上次绘制的所有内容,并再次渲染屏幕上的每个对象。
回到我们的游戏循环的例子,它目前没有执行它应该执行的事情,如果我们尝试运行代码,很明显窗口不响应输入,这是因为我们没有执行循环处理输入的三个重要步骤中的第一个步骤 ( 处理输入)。
Event handling (处理事件)
可以通过 bool Window :: pollEvent(sf :: Event&event) 从窗口顺序询问( polled )事件。 如果有一个事件等待处理,该函数将返回true,并且事件变量将填充(filled)事件数据。 如果不是,则该函数返回false。 同样重要的是要注意,一次可能有多个事件; 因此我们必须确保捕获每个可能的事件。 以下是典型的事件循环:
while (window.isOpen()) //游戏循环
{
sf::Event event;
while (window.pollEvent(event))
{
}
}
现在运行代码会产生更满意的结果——可以移动窗口、调整大小和最小化它。然而,仍然有一个问题——关闭按钮不起作用。SFML没有假设在用户点击关闭按钮后窗口应该关闭。也许我们想保存玩家的进度,或者先问问他们是否确定。这意味着我们必须自己实现关闭按钮功能。