Using views

Introduction

In this tutorial, you'll learn how to use SFML 2D views. Views are like 2D cameras, which allow you to move, zoom or scroll without having to move or resize the whole scene.

Defining a new view

Views are defined by the sf::View class, which is basically a 2D rectangle nicely wrapped in a camera-like interface.

A view can be created either with a center point and a half-size, or directly from a bounding rectangle :

sf::Vector2f Center(1000, 1000);
sf::Vector2f HalfSize(400, 300);
sf::View View1(Center, HalfSize);

// Or

sf::View View2(sf::FloatRect(600, 700, 1400, 1300));

All these parameters can be set and get at any time using the accessors :

View.SetCenter(500, 300);
View.SetHalfSize(200, 100);

// Or

View.SetFromRect(sf::FloatRect(300, 200, 700, 400));
sf::Vector2f  Center    = View.GetCenter();
sf::Vector2f  HalfSize  = View.GetHalfSize();
sf::FloatRect Rectangle = View.GetRect();

There are also two helper functions to move or zoom (resize) the view :

View.Move(10, -5); // Move the view of (10, -5) units
View.Zoom(0.5f);   // Zoom by a factor of 1/2 (ie. unzoom to make the view twice larger)

As you can see there's nothing complicated here, only a few functions to control the view's position and size.

Using a view

To use a view, you need to call the SetView function of the sf::RenderWindow class :

// Use our custom view
App.SetView(View);

Any object drawn after the call to SetView (and before the next one) will be affected by the view.
Once set, the render window keeps a link to the view so you can update it without calling SetView again, all your modifications will be automatically taken in account.

Every render window has a default view, which always matches the initial size of the window. You can access this view, and even modify it if needed, with the GetDefaultView function :

sf::View& DefaultView = App.GetDefaultView();

The default view is not updated when its window is resized : as a consequence, what's visible in your window will never be affected by its size (ie. you won't see more if you maximize the window), which is exactly what happens with a 3D camera.
However, you can easily setup a view which always keeps the same dimension as the window, by catching the sf::Event::Resized event and updating the view accordingly.

Accessing the default view is also convenient to go back to the initial view. For example, it can be useful if you want to draw a user interface on top of the game, which usually doesn't follow the camera.

App.SetView(View);

// Draw the game...

App.SetView(App.GetDefaultView());

// Draw the interface...

Window coordinates and view coordinates

When a custom view is set, or when your window has been resized, don't forget that objects coordinates no longer match the window pixels, be careful to handle conversions if needed (for example, when you test the mouse position with the sprites' rectangles). Always remember that what you actually see is the view rectangle, not the window one.

If you want to convert window coordinates to view coordinates, probably after a mouse clic, you can use the RenderWindow::ConvertCoords function :

// Get the cursor position in view coordinates
sf::Vector2f MousePos = App.ConvertCoords(App.GetInput().GetMouseX(), App.GetInput().GetMouseY());

By default, this function uses the view currently set in the window to perform the conversion. However, you can use any other view by passing its address as the third parameter (which is NULL by default).

Conclusion

2D views provide an easy and convenient way to deal with effects such as scrolling and zooming, with no performances penalty. The only thing to take care of when using views, is the possible conversions that could be needed if you try to map pixels to coordinates.