Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Scaling to pixels math  (Read 280 times)

0 Members and 2 Guests are viewing this topic.

WarpedJoy

  • Newbie
  • *
  • Posts: 1
    • View Profile
Scaling to pixels math
« on: February 18, 2025, 07:07:33 pm »
Hello, I am a new SFML and C++ programmer (but I've coded others) btw.

I am trying to get my game window to stay 16:9 whenever it's resized by scaling a 160 x 90 image and resizing the window to that sprite's scale.

Currently, it just.. well, I don't know how exactly to explain it, but the image is not scaling to the window's width.

Here's the code only necessary to share
int lastW = 1600; //window size at startup
int lastH = 900;
bool showDevTool1 = true;
float ratioW = 16.0f / 9.0f;
float ratioH = 9.0f / 16.0f;
std::string RatioHandles = "Images/Debug/Aspect_ratio_handles.png";

//Render window
int main() {
    sf::RenderWindow
    window(sf::VideoMode(lastW, lastH), "Gaem");

//16:9 ratio handles
        sf::Texture RHtexture;
        if (!RHtexture.loadFromFile(RatioHandles)) {
            return -1; // Exit if loading fails
        };
        sf::Sprite devTool1;
        devTool1.setTexture(RHtexture);

//Keep window open
    while (window.isOpen()) {
        sf::Event event;

//Close button closes window
    while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed)
                window.close();

//Can only resize as 16:9 ratio
            else if (event.type == sf::Event::Resized) {
                window.draw(devTool1);

//if width resized, do this
                if (lastW != event.size.width) {
                    std::cout << event.size.width;
                    std::cout << "---";
                    std::cout << RHtexture.getSize().x;
                    std::cout << "---";
                    devTool1.setScale(
                        event.size.width / RHtexture.getSize().x / 10,
                        lastH / RHtexture.getSize().y / 10);
                    window.setSize(sf::Vector2u(RHtexture.getSize().x * event.size.width, event.size.height));
                    lastW = event.size.width;
                    break;
                }

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11145
    • View Profile
    • development blog
    • Email
Re: Scaling to pixels math
« Reply #1 on: February 18, 2025, 07:41:03 pm »
Someone once wrote a nice function to get a letterbox view, i.e. it draws black borders around the area while retaining your aspect ration, see the wiki: https://github.com/SFML/SFML/wiki/Source%3A-Letterbox-effect-using-a-view

Hope this helps, otherwise you might need to try to explain more what you're trying to achieve.
Official FAQ: https://www.sfml-dev.org/faq/
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Hapax

  • Hero Member
  • *****
  • Posts: 3402
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Scaling to pixels math
« Reply #2 on: February 19, 2025, 06:59:02 pm »
I think that manipulating the window's size should always be considered to be the last resort.
It is not very user friendly at all. It becomes a pain for users that want to place windows in specific places, for example.

The letter box view idea - as shown in the link above - is probably the best solution to this: the user gets the window they want and the program gets the ratio it wants and also can use the size of the window.
Additionally, this can be extended to use the window fully for user interface tools while still keeping the "sprite" at its own ratio (of course, the sprite could represent an entire game display).

With that said, you can use the viewport and view size from the letterbox code to resize the window, if you absolutely must resize the window.

In addition, in the code you have shown, you have a ratio for both width and height. However, these are the ratios when compared to the other so both should never be used; one of them should be 1. Not that those constants are being used...

Also, you shouldn't need a sprite to resize the window. You could, for example, just resize the height of the window based on its width:
constexpr float ratioH{ 9.f / 16.f };
const unsigned int windowWidth{ window.getSize().x };
window.setSize({ windowSize.x, static_cast<unsigned int>(windowSize.x * ratioH) });
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*