1
Window / Get rid of letterboxing
« on: November 01, 2017, 06:44:16 am »
So currently I've got code that is able to pick a correct logical width given a fixed logical height (180px) for the game resolution. It calculates the logical width based on the screen resolution you're on and adjusts the fixed logical height.
For example..
Say I want my logical height of the game to be at 180px. The ideal logical width would be: 320px and the ideal logical height would stay at 180px since my display resolution is set to 1920 x 1080 and it's a perfect division.
If the display resolution is 1600 x 1024, the ideal logical size would be: 266.667 x 170.667 (integer truncation to 266 x 170).
I'm just not sure how to implement it correctly. So far it works on 1920 x 1080, but if I change the display to 1600 x 1024 and go fullscreen (borderless), the screen starts flickering. I can also see (past the flickering) that there is also still letterboxing. I believe that has to do with the posX and sizeX and posY and sizeY variables, but I'm not sure how to modify those correctly (code below).
My logical width and height calculation code:
So currently to implement scaling the view I'm using the letterboxing code provided by Hapax:
https://github.com/SFML/SFML/wiki/Source%3A-Letterbox-effect-using-a-view
I'm honestly just not sure how to apply it here though. I don't know what to set sizeX and sizeY to (I'm pretty sure posX and posY would be 0). And I'm not sure why the screen flickers when I go on a lower resolution (1600x1024).
Current adjusted letterbox removal code:
And here is where I create the window and apply the view to the window:
//Multiply the logical size of the window by 3 so its not so tiny
int window_w = GameWindow::getIdealSize().x * 3;
int window_h = GameWindow::getIdealSize().y * 3;
//Create the window
window = GameWindow::createWindow(window_w, window_h);
sf::View view;
sf::Vector2<int> logicalSize = GameWindow::getIdealSize();
view.setSize( logicalSize.x, logicalSize.y );
view.setCenter( view.getSize().x / 2, view.getSize().y / 2 );
view = GameWindow::getNoLetterboxView( view, logicalSize.x, logicalSize.y );
while(running) {
//Handle events here (toggle fullscreen by pressing F key)
handleEvents();
//Update logic code here
//...
//Rendering and applying view to window here
window->clear();
window->setView(view);
window->draw(bg);
window->draw(spr);
window->display();
}
The game window looks fine. But when I go to fullscreen (borderless):
I've got the correct logical size (unless I shouldn't be truncating it, should I be flooring/ceiling it?). What can I do to fix both the flickering and letterboxing still showing up?
For example..
Say I want my logical height of the game to be at 180px. The ideal logical width would be: 320px and the ideal logical height would stay at 180px since my display resolution is set to 1920 x 1080 and it's a perfect division.
If the display resolution is 1600 x 1024, the ideal logical size would be: 266.667 x 170.667 (integer truncation to 266 x 170).
I'm just not sure how to implement it correctly. So far it works on 1920 x 1080, but if I change the display to 1600 x 1024 and go fullscreen (borderless), the screen starts flickering. I can also see (past the flickering) that there is also still letterboxing. I believe that has to do with the posX and sizeX and posY and sizeY variables, but I'm not sure how to modify those correctly (code below).
My logical width and height calculation code:
sf::Vector2<int> GameWindow::getIdealSize() {
sf::VideoMode desktop = sf::VideoMode::getDesktopMode();
double display_width = desktop.width;//modes[0].width;
double display_height = desktop.height;//modes[0].height;
double ideal_width = 0; //we need to calculate this, we won't be using this fixed value anymore
double ideal_height = 180; //fixed height value
double aspect_ratio = display_width / display_height;
ideal_width = round(ideal_height * aspect_ratio);
//Portrait (comment this out as we're using landscape mode for this game, we have a fixed ideal_height set
//ideal_height = round(ideal_width / aspect_ratio);
//Perfect Pixel Scaling
if((int)display_width % (int)ideal_width != 0){
double d = round(display_width / ideal_width);
ideal_width = display_width / d;
}
if((int)display_height % (int)ideal_height != 0){
double d = round(display_height / ideal_height);
ideal_height = display_height / d;
}
//ideal_width and ideal_height must be even numbers
if((int)ideal_width & 1){
ideal_width+=1;
}
if((int)ideal_height & 1){
ideal_height++;
}
cout << "display_width: " << display_width << " display_height: " << display_height << " aspect_ratio: " << aspect_ratio << " ideal_width: " << ideal_width << " ideal_height: " << ideal_height << endl;
sf::Vector2<int> v(ideal_width, ideal_height);
return v;
}
sf::VideoMode desktop = sf::VideoMode::getDesktopMode();
double display_width = desktop.width;//modes[0].width;
double display_height = desktop.height;//modes[0].height;
double ideal_width = 0; //we need to calculate this, we won't be using this fixed value anymore
double ideal_height = 180; //fixed height value
double aspect_ratio = display_width / display_height;
ideal_width = round(ideal_height * aspect_ratio);
//Portrait (comment this out as we're using landscape mode for this game, we have a fixed ideal_height set
//ideal_height = round(ideal_width / aspect_ratio);
//Perfect Pixel Scaling
if((int)display_width % (int)ideal_width != 0){
double d = round(display_width / ideal_width);
ideal_width = display_width / d;
}
if((int)display_height % (int)ideal_height != 0){
double d = round(display_height / ideal_height);
ideal_height = display_height / d;
}
//ideal_width and ideal_height must be even numbers
if((int)ideal_width & 1){
ideal_width+=1;
}
if((int)ideal_height & 1){
ideal_height++;
}
cout << "display_width: " << display_width << " display_height: " << display_height << " aspect_ratio: " << aspect_ratio << " ideal_width: " << ideal_width << " ideal_height: " << ideal_height << endl;
sf::Vector2<int> v(ideal_width, ideal_height);
return v;
}
So currently to implement scaling the view I'm using the letterboxing code provided by Hapax:
https://github.com/SFML/SFML/wiki/Source%3A-Letterbox-effect-using-a-view
I'm honestly just not sure how to apply it here though. I don't know what to set sizeX and sizeY to (I'm pretty sure posX and posY would be 0). And I'm not sure why the screen flickers when I go on a lower resolution (1600x1024).
Current adjusted letterbox removal code:
sf::View GameWindow::getNoLetterboxView(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's viewport accordingly in order to archieve a letterbox effect.
// A new view (with a new viewport set) is returned.
float windowRatio = 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; //not sure what to set this to
posX = 0;
}
else {
sizeY = windowRatio / viewRatio; //not sure what to set this to
posY = 0;
}
view.setViewport( sf::FloatRect(posX, posY, sizeX, sizeY) );
return view;
}
// Compares the aspect ratio of the window to the aspect ratio of the view,
// and sets the view's viewport accordingly in order to archieve a letterbox effect.
// A new view (with a new viewport set) is returned.
float windowRatio = 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; //not sure what to set this to
posX = 0;
}
else {
sizeY = windowRatio / viewRatio; //not sure what to set this to
posY = 0;
}
view.setViewport( sf::FloatRect(posX, posY, sizeX, sizeY) );
return view;
}
And here is where I create the window and apply the view to the window:
//Multiply the logical size of the window by 3 so its not so tiny
int window_w = GameWindow::getIdealSize().x * 3;
int window_h = GameWindow::getIdealSize().y * 3;
//Create the window
window = GameWindow::createWindow(window_w, window_h);
sf::View view;
sf::Vector2<int> logicalSize = GameWindow::getIdealSize();
view.setSize( logicalSize.x, logicalSize.y );
view.setCenter( view.getSize().x / 2, view.getSize().y / 2 );
view = GameWindow::getNoLetterboxView( view, logicalSize.x, logicalSize.y );
while(running) {
//Handle events here (toggle fullscreen by pressing F key)
handleEvents();
//Update logic code here
//...
//Rendering and applying view to window here
window->clear();
window->setView(view);
window->draw(bg);
window->draw(spr);
window->display();
}
The game window looks fine. But when I go to fullscreen (borderless):
- The screen flickers (I can barely even see the actual game)
- I can still see letterboxing on the sides
I've got the correct logical size (unless I shouldn't be truncating it, should I be flooring/ceiling it?). What can I do to fix both the flickering and letterboxing still showing up?