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

Author Topic: How to resize my sprite and not have it so stretched out?  (Read 12715 times)

0 Members and 1 Guest are viewing this topic.

Deathslice246

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
How to resize my sprite and not have it so stretched out?
« on: November 03, 2016, 02:26:04 pm »
What I'm trying to do as the moment is trying to resize my chessboard sprite so that it fits the entire screen when the user tries to resize the window but the problem that I'm having is that the sprite looks all stretched out and ugly.

So what I tried to do was to check for a resizing event and then I divide the new screen size with the old screen size and multiply it by 100 to get the scale factor in the x and y axis but this didn't help at all.

The video mode is set to 700, 703, 24 because that is the exact width, height and bit depth that the png image has so that is why I made that resolution the default one.

Main.cpp

#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Window/Event.hpp>
#include "Board.hpp"

void checkInput(sf::RenderWindow &, Board chessBoard);
void resizeObjects(sf::RenderWindow &, Board chessBoard, sf::Event);
void updateScreen(sf::RenderWindow &, sf::Sprite);

int main()
{
        sf::RenderWindow gameWindow(sf::VideoMode(700, 703, 24), "Chess");

        sf::Texture textureBoardPath;
     
        textureBoardPath.loadFromFile("ChessBoard.png");

        Board chessBoard(textureBoardPath);
       
        while (gameWindow.isOpen())
        {
                checkInput(gameWindow, chessBoard);
                updateScreen(gameWindow, chessBoard.getBoard());
        }

        return 0;
}

void checkInput(sf::RenderWindow &gameWindow, Board chessBoard)
{
        sf::Event event;

        while (gameWindow.pollEvent(event))
        {
                if (event.type == sf::Event::Closed)
                {
                        gameWindow.close();
                }
                else if (event.type == sf::Event::Resized)
                {
                        resizeObjects(gameWindow, chessBoard, event);
                }
        }
}

void resizeObjects(sf::RenderWindow &gameWindow, Board chessBoard, sf::Event event)
{
        float scaleXFactor = event.size.width / gameWindow.getView().getSize().x * 100;
        float scaleYFactor = event.size.height / gameWindow.getView().getSize().y * 100;

        chessBoard.resizeBoard(scaleXFactor, scaleYFactor);
}

void updateScreen(sf::RenderWindow &gameWindow, sf::Sprite chessBoard)
{
        gameWindow.clear();
        gameWindow.draw(chessBoard);
        gameWindow.display();
}
 

Board.hpp

#pragma once

#include <SFML/Graphics/Sprite.hpp>

class Board
{
        public:
                Board(const sf::Texture &);
                sf::Sprite getBoard() const;
                void resizeBoard(float, float);

        private:
                int board[8][8] =
                { -1,-2,-3,-4,-5,-3,-2,-1
                  -6,-6,-6,-6,-6,-6,-6,-6,
                   0, 0, 0, 0, 0, 0, 0, 0,
                   0, 0, 0, 0, 0, 0, 0, 0,
                   0, 0, 0, 0, 0, 0, 0, 0,
                   0, 0, 0, 0, 0, 0, 0, 0,
                   6, 6, 6, 6, 6, 6, 6, 6,
                   1, 2, 3, 4, 5, 3, 2, 1 };

                sf::Sprite spriteBoard;
                sf::Sprite chessPieces[32];

};
 

Board.cpp

#include "Board.hpp"
#include <SFML/Graphics/Texture.hpp>

Board::Board(const sf::Texture &textureBoardPath): spriteBoard(textureBoardPath)
{
}

sf::Sprite Board::getBoard() const
{
        return spriteBoard;
}

void Board::resizeBoard(float scaleXFactor, float scaleYFactor)
{
        spriteBoard.setScale(scaleXFactor, scaleYFactor);
}
 
« Last Edit: November 03, 2016, 02:28:05 pm by Deathslice246 »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
AW: How to resize my sprite and not have it so stretched out?
« Reply #1 on: November 03, 2016, 05:26:09 pm »
Are you adjusting the view to the new window size?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Deathslice246

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: How to resize my sprite and not have it so stretched out?
« Reply #2 on: November 03, 2016, 08:30:32 pm »
No, I have not use view anywhere in my code.  I figured that if I scaled the image, that the changes would be reflected when I executed the program. I will read what SFML has to say about the view class.

Deathslice246

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: How to resize my sprite and not have it so stretched out?
« Reply #3 on: November 07, 2016, 08:44:22 pm »
Well I need a little bit of help with this.

So initially, I load my sprite like this 

textureBoardPath.loadFromFile("ChessBoard.png");

sf::Vector2u backgroundSize = background.getTexture()->getSize();

gameWindow.create(sf::VideoMode(backgroundSize.x, backgroundSize.y), "Chess", sf::Style::Close | sf::Style::Resize);
 

This is fine because it will load the image properly and the image will not looked scretch because it will be set to the size of the image.  The problem is when the user resizes it.

 I have an if that checks for resize events and I do this in that if statement

gameView.setSize((float)event.size.width, (float)event.size.height);
gameWindow.setView(gameView);
background.setScale(
                                float(event.size.width) / float(background.getTexture()->getSize().x),
                                float(event.size.height) / float(background.getTexture()->getSize().y));
 

This stretches the image quite a bit and the reason is probably because as the targetSize gets bigger, the background width and height does not change which means that the scale ratio is off(I'm not sure if that is the case though). Any guidances?

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to resize my sprite and not have it so stretched out?
« Reply #4 on: November 07, 2016, 11:21:28 pm »
By "stretched", do you mean larger or altered shape (where ratio of width to height changes)?

If you mean larger and you don't want it to increase in size when the window is sized larger, don't change the size of "background" while still adjusting the view to match the window.

If you mean altered shape, you will need to lock the aspect ratio of the background's scale (or the view).
You may find some use of this code that modifies a view to give a 'letter box' effect, keeping the visible portion's aspect ratio:
https://github.com/SFML/SFML/wiki/Source%3A-Letterbox-effect-using-a-view
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Deathslice246

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: How to resize my sprite and not have it so stretched out?
« Reply #5 on: November 07, 2016, 11:47:12 pm »
Here are two snapshots of the image with and without the screen being maximized.

http://imgur.com/a/UTZO2

See how the second image looks all ugly and stretched.

That is what I mean.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to resize my sprite and not have it so stretched out?
« Reply #6 on: November 08, 2016, 12:15:51 am »
I thought as much (although you haven't said what you want to happen).

Therefore:
If you mean larger and you don't want it to increase in size when the window is sized larger, don't change the size of "background" while still adjusting the view to match the window.

If you mean altered shape, you will need to lock the aspect ratio of the background's scale (or the view).
You may find some use of this code that modifies a view to give a 'letter box' effect, keeping the visible portion's aspect ratio:
https://github.com/SFML/SFML/wiki/Source%3A-Letterbox-effect-using-a-view
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Deathslice246

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: How to resize my sprite and not have it so stretched out?
« Reply #7 on: November 08, 2016, 01:36:01 am »
Well, I would like to adjust the size of the image as the screen grows and shrink so that it doesn't look all stretched and I don't really want to go for a letterbox effect.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to resize my sprite and not have it so stretched out?
« Reply #8 on: November 08, 2016, 02:56:56 am »
You want it to be resized with the window but not lose its aspect ratio or you don't want it to be resized with the window?
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Deathslice246

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: How to resize my sprite and not have it so stretched out?
« Reply #9 on: November 08, 2016, 03:51:04 am »
To put it this way, I want my image to look more or less the same quality before it was resizes(so I guess to resize with the window and not lose it's aspect ratio). I don't know how else I can say it to you.

Mister VistA

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: How to resize my sprite and not have it so stretched out?
« Reply #10 on: November 08, 2016, 03:34:32 pm »
There are two ways that I would try to accomplish this:

1. Keep the game board the original size and have a scaled background. This would essentially allow more of the background to be displayed when the window size increases, while keeping the board the same size. Of course, this isn't a downsize friendly option.

2. Obtain your scaling factor and then use the smallest factor for both dimensions. This will keep a 1:1 aspect ratio and allow your board to grow without overshooting either the x or y axis. For instance, if your board is 100x100 pixels, and your window is 100x100, then resizing your window to 200x400 will give you a scaling factor of 2 and 4 (respectively for x and y). What you want to do is only use the lowest value (2) for both x and y scaling operations. That will result in a game board that is 200x200 I instead of 200x400.

Also, you'll probably want to take downsizing into consideration, in which case, I believe you'll want the lowest absolute scaling factor (as in absolute values).

Just two quick and easy ways that I can think of to tackle this problem. Personally, I would try to implement the second option. You'll also need to use the same scaling factor for your chess piece size and positions as well.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to resize my sprite and not have it so stretched out?
« Reply #11 on: November 08, 2016, 03:56:50 pm »
so I guess to resize with the window and not lose it's aspect ratio
This is a form of letter-boxing, which I pointed you in the direction of that code.

Mister VistA, above, posted the answer I would probably use. However, just for options, there is another choice (although it's very similar):
Instead of scaling your board to match the new view size (which is the new window size), you could consider keeping the board co-ordinates the same by manipulating the view instead i.e. scale the view instead of the objects.
Work out the scale factors in the same way (using the ratio of object size to the window size) and then apply them to the view.
So, using Mister VistA's example, the values would be:
board: 100x100.
window: 200x400.
scaling factors of 2 (x) and 4 (y).
Divide the window size by the lowest factor to set the view:
lowest factor: 2.
view size: (200 / 2, 400 / 2) = 100x200

This scales the objects as normal to fit the window without modifying the co-ordinates used for the objects but also adds 'padding' to the view to match the window so that the objects stay at the correct aspect ratio.

Note that sf::Vectors can be divided by a scalar:
const float lowestFactor = 2.f; // calculate this as described above
const sf::Vector2f windowSize(window.getSize());
const sf::Vector2f viewSize = windowSize / lowestFactor;

Important!
Remember to correct set the view's centre whenever the view size is changed (if you're changing the size of an existing view). If you require (0, 0) to be at the top-left corner, the view's centre should be the view's size divided by 2.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Deathslice246

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: How to resize my sprite and not have it so stretched out?
« Reply #12 on: November 08, 2016, 04:34:45 pm »
So this is what I was able to come up with. it's ok but the problem is that as I increase the size of the screen, the image does not increase and a black portion appears on the screen(meaning it is not fitting to the entire screen).

Here is the relevant code

else if (event.type == sf::Event::Resized)
{
                        // Get the new size of the window
                        sf::Vector2f visibleArea = sf::Vector2f((float)event.size.width, (float)event.size.height);

                        // Find the scale factor in the x and the y axis
                        const float scaleXFactor = visibleArea.x / background.getLocalBounds().width;
                        const float scaleYFactor = visibleArea.y / background.getLocalBounds().height;

                        // Pick the smallest factor and get the new view size.
                        const float lowestFactor = std::min(scaleXFactor, scaleYFactor);
                        const sf::Vector2f windowSize(sf::Vector2f(gameWindow.getSize()));
                        const sf::Vector2f viewSize = windowSize / lowestFactor;

                        gameView.setSize(viewSize);
                        gameView.setCenter(viewSize / 2.0f);
                        gameWindow.setView(gameView);
}
 

To put it into perspective, this is what I do initially at the start of the program.

background.setTexture(textureManager.getTexture("ChessBoard")); // get the texture and set it.

sf::Vector2u backgroundSize = background.getTexture()->getSize(); // get its size

// initially set the window size to be the max size of the image.
gameWindow.create(sf::VideoMode(backgroundSize.x, backgroundSize.y), "Chess", sf::Style::Default);
gameWindow.setFramerateLimit(60);

// and set it as the view.
sf::FloatRect visibleArea(0.0f, 0.0f, (float)backgroundSize.x, (float)backgroundSize.y);
gameView = sf::View(visibleArea);
gameWindow.setView(gameView);
 
« Last Edit: November 08, 2016, 04:46:52 pm by Deathslice246 »

Deathslice246

  • Newbie
  • *
  • Posts: 8
    • View Profile
    • Email
Re: How to resize my sprite and not have it so stretched out?
« Reply #13 on: November 08, 2016, 08:25:14 pm »
Interesting, if I change

const sf::Vector2f windowSize(sf::Vector2f(gameWindow.getSize()));
 

to

const sf::Vector2f windowSize(gameWindow.getView().getSize());
 

it removes the black portion that appears when I maximized the screen but now the image is even bigger. :/

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to resize my sprite and not have it so stretched out?
« Reply #14 on: November 09, 2016, 02:25:13 am »
visibleArea is set to the new window size so there's no need to use the windowSize const; just use visibleArea instead (or you could rename visibleArea to windowSize ;))
Note that you can construct that vector directly:
const sf::Vector2f visibleArea(static_cast<float>(event.size.width), static_cast<float>(event.size.height));

Interesting, if I change[...]
You are not setting the view to the size of the window so don't use the view's size to set the size of the window.

The design of this scaling is intended to create space in the window when the window doesn't match the object's aspect ratio but you do keep mentioning "black portion"s, which I presume are the space parts so I'm not sure what you want.
One other possibility is that you want to scale to always fill the entire window and 'chop off' the parts that don't fit that aspect ratio. Is that correct? If so, try using the highest scale factor instead of the lowest one.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*