Search code examples
c++alignmentsfml

C++ How do I stop resizing Sf :: Text on screen resize ( but at the same position)


Im making map editor and i want to add resizing window but when i resize window my gui elements are resizing too how can i stop that, i stop resizing map surface with set new size of map view but i cant do it with gui elements because it changes positions of gui elements

    if(events.type == sf::Event::Resized)
    {
        m_defaultViewSize.x = events.size.width;
        m_defaultViewSize.y = events.size.height;
        m_mapView.setSize(m_defaultViewSize);
        m_mapView.setSize(m_mapView.getSize() / m_zoomScale);// Apply the zoom level
        m_stateData->window->setView(m_mapView);
    }

sorry for my poor english


Solution

  • If you currently DO NOT have a GUI view your rendering code might look something like:

    m_stateData->window->clear();
    m_stateData->window->setView(m_mapView);
    m_stateData->window->draw(m_map);
    m_stateData->window->draw(m_gui);
    m_stateData->window->display();
    

    This is drawing the GUI on the same view as the map, so if the map view changes so does the GUI. This might be fine if the map does not change, but if you are planning on moving, scaling or rotating the map it would be best to create a GUI view.

    Now rendering might look like this:

    m_stateData->window->clear();
    m_stateData->window->setView(m_mapView);
    m_stateData->window->draw(m_map);
    m_stateData->window->setView(m_guiView);
    m_stateData->window->draw(m_gui);
    m_stateData->window->display();
    

    This is fine until we resize the window.
    After resizing the window the view stays the same even though the viewport has changed size. If the window has been made larger twice horizontally but not vertically, the GUI is going to be stretched horizontally.
    I personally do not like stretching, I do not think it looks nice. We should resize the view.
    You could resize the view the same way you resized the map view.

    m_guiView.setSize(m_defaultViewSize);
    m_guiView.setSize(m_guiView.getSize() / m_zoomScale);
    

    This will stop resizing the GUI elements, but their position will be the same as if we had not resized the window. You might want to reposition the GUI elements. One simple way of doing this is by storing the GUI elements position as a ratio along the screen horizontally and vertically. So, the top left might be (-0.5, -0.5) and the bottom right might be (0.5, 0.5). This might look like (with a view centered on (0, 0)):

    // get ratio position of gui element
    sf::Vector2f ratio_position = {
        (m_gui.getPosition().x) / m_guiView.getSize().x,
        (m_gui.getPosition().y) / m_guiView.getSize().y
    };
    // resize view
    m_guiView.setSize(m_defaultViewSize);
    m_guiView.setSize(m_guiView.getSize() / m_zoomScale);
    // set position of gui element
    m_gui.setPosition(
        (ratio_position.x)* m_guiView.getSize().x,
        (ratio_position.y) * m_guiView.getSize().y
    );
    

    You could also have this be functionality of a class.

    You can use things other than ratios as well.
    You could make GUI elements relative to corners of the screen, or other ratios. So You could have Health bar, Stamina bar, Mana bar all relative to the top left of the view. This would just be calculating the top left position (view center - half of the view size) and then adding on some relative position (for example, (0, 0) for health bar, (0, 32) for stamina bar etc).

    I suggest you look at how other Game Engines handle GUI. Unity uses Anchor Points. Godot uses containers. Try and recreate a system you like.