Using SFML - JayhawkZombie/EECS581Project GitHub Wiki
##Using SFML
This project uses SFML for rendering, audio, and networking.
SFML is not a whole engine in itself, but rather more like an abstraction library/API that can leverage to make it much easier for us to render things to the screen, play audio, and do networking.
There are 5 main modules:
- System
- Window
- Graphics
- Audio
- Networking
We make use of every module, so be sure to link them (and include the proper DLLs if you require.
Rendering in SFML:
SFML is also used as a window manager, not dissimilar to how GLEW is used when using raw OpenGL. Using the Graphics
module, we can easily render things.
Firstly, we can create a window:
sf::RenderWindow window(sf::VideoMode(800 /*Width*/, 800 /*Height*/, "My Window" /*Window title*/, sf::Style::Default, contextSettings);
//Style and contextSettings are optional
You can check if the window is open:
while (window.isOpen()) ...
When we have a render window, we can use it to poll events coming in from the OS:
sf::Event e;
while (window.pollEvents(e)) {
if (e.type == ...)
}
There are many events that can be retrieved:
- Closed
- Resized
- LostFocus
- GainedFocus
- TextEntered
- KeyPressed
- KeyReleased
- MouseWheelScrolled /Deprecated/
- MouseWheelMoved
- MouseButtonPressed
- MouseButtonReleased
- MouseMoved
- MouseEntered
- MouseLeft
There are Joystick events available, but we are not using Joysticks.
If we want to render, we can create an instance of any class derived from SFDrawable:
sf::RectangleShape shape;
shape.setSize(sf::Vector2f(100 /*Width*/, 100 /*Height*/));
shape.setPosition(sf::Vector2f(0 /*X pos*/, 150 /*Y pos*/));
...
window.clear();
window.draw(shape);
window.display();
Window.draw(...) will write to the frame buffer, but will not cause glSwapBuffers
to be called, which will not cause the frame being drawn to the screen to be updated. Calling Window.display() will actually make the screen be updated with the most recently updated frame buffer.
###Rendering with textures
A texture is nothing but an image. A texture can be applied to a primitive, like sf::RectangleShape
, quite easily. You also do not have to use the entire texture. You can specify a portion of the texture to apply to the shape, but the region you specify will cover the entire primitive.
sf::Texture tex;
tex.loadFromFile("SomeFilePath");
sf::Sprite sprite;
//Do some stuff with sprite
sf::IntRect textureRegion(0, 0, 100, 100); //Left, top, right, bottom
/*
___Top_______________________
| | | |
Left | | Right | |
| | | |
|_Bottom__|_________|________|
| | | |
| | | |
| | | |
|_________|_________|________|
*/
sprite.setTextureRect(textureRegion);
sprite.setTexture(tex);
...
window.draw(sprite);
...
Then your sprite will be drawn to the screen, using the region in the texture you specified. If you do not specify a region in the texture to use, it will use the whole texture and distort the texture to fit the primitive.
There is a lot more you can do with SFML to render. See this page
By design, SFML can only draw to the window in the same thread in which that window was made active. So you cannot render to the current render window from a thread that did not create the window unless you make the window inactive using window.setActive(false)
and then use the window in a new thread. The window will be activated automatically in the other thread. This actually makes the OpenGL context in the other thread invalid, and makes a valid OpenGL context in the thread you are currently in, but it makes the process simpler.
The same thing goes for events. Events need to be polled in the same thread in which the window is active. The Engine does not do this in a separate thread and uses the main thread for this. Do not, under any circumstances, render from outside the main thread.