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

Author Topic: [SOLVED] How to make my game board occupy as much window space as possible  (Read 1471 times)

0 Members and 2 Guests are viewing this topic.

gera

  • Newbie
  • *
  • Posts: 2
    • View Profile
I want to draw my rectangular game board in a resizable window. When the window's aspect ratio does not match there should be black margins at either top&bottom or left&right.

Right now I have margins on both sides (see screenshot). This is because I first set view on a square with a side equal to the board's larger dimension and then I set its viewport to account for window's aspect ratio. I think to achieve what I want the viewport should take board's dimensions into account as well, but I don't see how. Please help.

// -*- compile-command: "g++ board.cpp -o board -lsfml-graphics -lsfml-window -lsfml-system && ./board"; -*-

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Window.hpp>

int main()
{
        const int BW = 40;
        const int BH = 30;

        sf::RenderWindow window(sf::VideoMode(960, 540), "Board drawing test");
        window.setFramerateLimit(10);

        const int MAX_DIMENSION = std::max(BW,BH);
        sf::View view({-(MAX_DIMENSION-BW)/2, -(MAX_DIMENSION-BH)/2, MAX_DIMENSION, MAX_DIMENSION});
        window.setView(view);

        while (window.isOpen()) {
                sf::Event event;
                while (true) {
                        bool moreEvents = window.pollEvent(event);
                        switch (event.type) {
                                case sf::Event::Closed:
                                        window.close();
                                        break;
                                case sf::Event::Resized:
                                        int ww = event.size.width;
                                        int wh = event.size.height;

                                        if (ww > wh) {
                                                float aspect = (float)wh/ww;
                                                float empty = 1.0f - aspect;
                                                view.setViewport(sf::FloatRect(empty/2, 0.0f, aspect, 1.0));
                                        } else {
                                                float aspect = (float)ww/wh;
                                                float empty = 1.0f - aspect;
                                                view.setViewport(sf::FloatRect(0.0f, empty/2, 1.0, aspect));
                                        }
                                        window.setView(view);
                                        break;
                        }
                        if (!moreEvents)
                                break;
                }

                window.clear();

                // blue rectangle, filling the entire board
                sf::RectangleShape shape(sf::Vector2f(BW, BH));
                shape.setFillColor(sf::Color(0, 0, 255));
                window.draw(shape);
                // red square at the corner of the board
                shape.setFillColor(sf::Color(255, 0, 0, 255));
                shape.setPosition(BW-1, BH-1);
                shape.setSize(sf::Vector2(1.0f, 1.0f));
                window.draw(shape);

                window.display();
        }
       
        return 0;
}
 
« Last Edit: May 07, 2024, 08:26:28 pm by gera »

kimci86

  • Full Member
  • ***
  • Posts: 128
    • View Profile
Re: How to make my game board occupy as much window space as possible
« Reply #1 on: May 07, 2024, 07:33:54 pm »
You are trying to achieve a letterbox effect.
There is an example implementation on the wiki: https://github.com/SFML/SFML/wiki/Source:-Letterbox-effect-using-a-view

gera

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: How to make my game board occupy as much window space as possible
« Reply #2 on: May 07, 2024, 08:14:31 pm »
Thanks, with this function everything works!

// -*- compile-command: "g++ board.cpp -o board -lsfml-graphics -lsfml-window -lsfml-system && ./board"; -*-

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/Window.hpp>
#include <iostream>

sf::View getLetterboxView(sf::View view, int windowWidth, int windowHeight) {
    // Compares the aspect ratio of the window to the aspect ratio of the view,
    // and sets the view&#39;s viewport accordingly in order to achieve a letterbox effect.
    // A new view (with a new viewport set) is returned.

    float windowRatio = (float) windowWidth / (float) windowHeight;
    float viewRatio = view.getSize().x / (float) view.getSize().y;
    float sizeX = 1;
    float sizeY = 1;
    float posX = 0;
    float posY = 0;

    bool horizontalSpacing = true;
    if (windowRatio < viewRatio)
        horizontalSpacing = false;

    // If horizontalSpacing is true, the black bars will appear on the left and right side.
    // Otherwise, the black bars will appear on the top and bottom.

    if (horizontalSpacing) {
        sizeX = viewRatio / windowRatio;
        posX = (1 - sizeX) / 2.f;
    }

    else {
        sizeY = windowRatio / viewRatio;
        posY = (1 - sizeY) / 2.f;
    }

    view.setViewport( sf::FloatRect(posX, posY, sizeX, sizeY) );

    return view;
}

int main()
{
        const int BW = 70;
        const int BH = 40;

        sf::RenderWindow window(sf::VideoMode(960, 540), "Board drawing test");
        window.setFramerateLimit(10);

        sf::View view({0.0f, 0.0f, BW, BH});

        while (window.isOpen()) {
                sf::Event event;
                while (true) {
                        bool moreEvents = window.pollEvent(event);
                        switch (event.type) {
                                case sf::Event::Closed:
                                        window.close();
                                        break;
                                case sf::Event::Resized:
                                        view = getLetterboxView(view, event.size.width, event.size.height);
                                        break;
                        }
                        if (!moreEvents)
                                break;
                }

                window.setView(view);
                window.clear();

                // blue rectangle, filling the entire board
                sf::RectangleShape shape(sf::Vector2f(BW, BH));
                shape.setFillColor(sf::Color(0, 0, 255));
                window.draw(shape);
                // red square at the corner of the board
                shape.setFillColor(sf::Color(255, 0, 0, 255));
                shape.setPosition(BW-1, BH-1);
                shape.setSize(sf::Vector2(1.0f, 1.0f));
                window.draw(shape);

                window.display();
        }
       
        return 0;
}