From translator: This article is the ninth in the translation cycle of the official SFML library guide. Past article can be found here. This series of articles aims to provide people who do not know the original language the opportunity to get acquainted with this library. SFML is a simple and cross-platform multimedia library. SFML provides a simple interface for developing games and other multimedia applications. The original article can be found here . Dedicated to Eva White. Happy Birthday;). Let's start.Introduction
This article explains how to open and manage a window. Drawing in a window goes beyond the tasks solved by the
sfml-window
module; This task is solved by the
sfml-graphics
module. However, window management using the
sfml-graphics
module is also done, so reading this article is important anyway.
Opening window
In SFML, windows are represented by the
sf :: Window class. A window can be created directly from the constructor of this class:
#include <SFML/Window.hpp> int main() { sf::Window window(sf::VideoMode(800, 600), "My window"); ... return 0; }
The first argument is the video mode, determines the size of the window being created (the size of the window area, without the window title and borders). Here we have created a window of 800x600 pixels.
The
sf :: VideoMode class has interesting static functions with which you can get desktop resolution or available video modes. We advise you to look at the documentation for this class.
The second argument is the name of the window being created.
The
sf :: Window class constructor can accept the third argument: a style that allows you to choose which decorations and functions you want to use.
You can use any combination of the following styles:
sf::Style::None | No decorations (used, for example, for loading screens); This style cannot be used with others. |
sf::Style::Titlebar | The window has a caption. |
sf::Style::Resize | You can resize the window and the open button appears full screen |
sf::Style::Close | A close button appears near the window. |
sf::Style::Fullscreen | The window opens in full screen mode; This style cannot be combined with others and requires an available video mode. |
sf::Style::Default | Standard style, which is the abbreviation Titlebar | Resize | Close Titlebar | Resize | Close |
There is also a fourth argument that defines the specific OpenGL options. This topic is discussed in more detail in the article on OpenGL.
If you want to create a window
after creating an instance of
sf :: Window or re-creating a window with a different video mode or title, you can use the
create
function. It takes the same arguments as the class constructor.
#include <SFML/Window.hpp> int main() { sf::Window window; window.create(sf::VideoMode(800, 600), "My window"); ... return 0; }
Window revitalization
If you try to execute the code above (by deleting the "..."), you are unlikely to see anything. First, because the program terminates immediately. Secondly, because the program does not handle events; so even if you added this code to an infinite loop, you will see a dead window that cannot be moved or closed.
Let's add some code to make this program more interesting:
#include <SFML/Window.hpp> int main() { sf::Window window(sf::VideoMode(800, 600), "My window"); // , while (window.isOpen()) { // , sf::Event event; while (window.pollEvent(event)) { // : if (event.type == sf::Event::Closed) window.close(); } } return 0; }
The code above opens the window and destroys it when the user closes it. Let's take a closer look at how it works:
First, we added a loop that ensures that the application will be updated / supplemented before the window closes. Most (if not all) SFML programs will have a similar construction; sometimes this loop is called the
main loop or
game loop .
Then, the first thing we want to do inside our cycle is to check for unprocessed events. Notice that we use a
while
to handle all pending events. The
pollEvent
function returns
true
if there are events waiting to be processed, or
false
if there are none.
Whenever an event occurs, we have to check its type (closing the window? Pressing the key? Moving the mouse? Connecting the joystick? ...), and, if we are interested in this, respond accordingly. Here we only check if the
Event::Closed
event occurred, which is triggered if the user tries to close the window. At this point, the window is still open and we must explicitly close it using the following functions. This allows you to do something before closing the window, for example, save the current state of the application or display a message.
People often forget about the event loop, because they don't need to handle events (they use keyboard input instead). Without an event loop, the window will stop responding. It is important to remember that the event loop has two roles: in addition to handling custom events, it is also handling internal window events that may be caused by moving or resizing a window.
After the window is closed, the main loop ends and the program ends its execution.
At this point, you probably noticed that we did not talk about drawing something in the window. As stated in the introduction, this is not the task of the
sfml-window
module. Drawing objects (sprites, text, or shapes) will be discussed in
sfml-graphics
articles.
To draw something, you can also use OpenGL directly and ignore the
sfml-graphics
module.
sf :: Window creates an OpenGL context and is ready to accept calls to OpenGL. You can read more about this topic in the article on the use of OpenGL.
Don't expect to see something interesting in a new window: we can see some color (black or white), or the contents of the past application that used OpenGL, or ... something else.
Playing with the window
Of course, SFML allows you to play with your windows. Basic window operations, such as resizing, positioning, names, or icons are supported, but, unlike special GUI libraries (Qt, wxWidgets), SFML does not provide advanced functionality. SFML windows are intended only to provide an environment for OpenGL or SFML.
// ( ) window.setPosition(sf::Vector2i(10, 50)); // window.setSize(sf::Vector2u(640, 480)); // window.setTitle("SFML window"); // sf::Vector2u size = window.getSize(); unsigned int width = size.x; unsigned int height = size.y; ...
You can refer to the API documentation for a complete list of
sf :: Window functions.
In case you really need advanced functionality for your window, you can create one window with another library and embed it in SFML. To do this, you can use another constructor or create a function that passes
sf :: Window descriptor to an existing window. In this case, SFML will create a drawing context inside the passed window and catch all events without interfering with the parent window manager.
sf::WindowHandle handle = ; sf::Window window(handle);
If you need an extra, very specific function, you can do it differently: create an SFML window, get its handle and do what SFML does not allow.
sf::Window window(sf::VideoMode(800, 600), "SFML window"); sf::WindowHandle handle = window.getSystemHandle(); // ,
Integrating SFML with other libraries requires work and will not be described here, but you can refer to other articles, examples, or posts on forums.
Frame rate control
Sometimes, when an application is running fast, you may notice visual artifacts. The reason is that the update frequency of your application is not synchronized with the frame scan of your monitor, and as a result, the lower part of the previous frame is mixed with the top of the next one.
The solution to this problem is to activate vertical synchronization. Synchronization is performed automatically by the video card and can be simply turned on or off using the
setVerticalSyncEnabled
function:
window.setVerticalSyncEnabled(true);
After this call, the application will run at a certain frequency equal to the monitor refresh rate.
Sometimes the call to
setVerticalSyncEnabled
has no effect: most likely because vertical synchronization is turned off in the driver settings of your video card. You must enable the “controlled by application” option in the video driver settings.
You may want your application to run at a given frame rate, instead of the monitor refresh rate. This can be achieved by calling
setFramerateLimit
:
window.setFramerateLimit(60);
Unlike
setVerticalSyncEnabled
, this function is implemented by SFML and uses the combination
sf :: Clock and
sf::sleep
. It is important to note that this function is not 100% reliable, especially for high frame rates: the possibilities of
sf::sleep
depend on the OS and equipment; the minimum pause time is 10-15 milliseconds. Do not rely on this feature if you are building an application that is highly time dependent.
Never use
setVerticalSyncEnabled
and
setFramerateLimit
together. This can cause bad consequences.
Things you need to know about windows
Below is a list of what you can and cannot do with SFML windows.
You can create multiple windows.
SFML allows you to create multiple windows, as well as process their events and manage them in the main thread or in multiple threads (but ... see below). In this case, do not forget to create an event loop for each of them.
So far, many monitors are not supported.
SFML implicitly manages multiple monitors. For this reason, you cannot select on which monitor the window will appear, and you cannot create more than one full-screen window. This should be fixed in future releases.
Window events must be processed in a window stream.
This is a serious deterrent for most operating systems: the event-handling cycle (more precisely, the
pollEvent
or
waitEvent
) should be called in the same thread that the window was created in. This means that if you want to create a dedicated thread for handling events, you must make sure that the window is created in the same thread. If you really want to divide tasks between threads, it is more convenient to handle events in the main thread, and perform window operations (for example, drawing graphics) in a separate thread. This configuration will also be compatible with the other limitations described below.
On Mac OS X, window maintenance and event handling must be done in the main thread.
Yeah, that's true. Mac OS X will not allow you to create a window or process events in a stream other than the main one.
On Windows, a window larger than the desktop is not processed correctly.
For some reason, Windows does not allow windows to be opened that is larger than the desktop. This affects windows created with
VideoMode::getDesktopMode()
: if you use window decorations (borders and title), you will get a window that is slightly larger than the desktop.
Next article:
Event handling .