Piszę warcaby. Chciałbym aby mój program działał dobrze na różnych rozdzielczościach.
1. Poszperałem trochę w googlach i znalazłem funkcję
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'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;
posX = (1 - sizeX) / 2.f;
}
else
{
sizeY = windowRatio / viewRatio;
posY = (1 - sizeY) / 2.f;
}
view.setViewport(sf::FloatRect(posX, posY, sizeX, sizeY));
return view;
}
Dzięki niej po zmianie rozmiaru okna, w przypadku gdy stosunek szerokości do wysokości jest inny niż na moim obiekcie Sprite, u góry i na dole lub po bokach pojawiają się czarne paski.
2. Domyślam się też, że jeżeli aplikacja ma działać na różnych rozdzielczościach, to powinienem użyć dużych grafik pasujących do największej docelowej rozdzielczości.
Jeśli ktoś będzie miał mniejszy ekran to ewentualnie pomniejszy się grafiki.
Gdybym natomiast próbował je rozciągnąć to by się wszystko rozmazało.
3. Używam też funkcji
bool isSpriteClicked(sf::Sprite object, sf::Mouse::Button button, sf::RenderWindow& window)
{
if (sf::Mouse::isButtonPressed(button))
{
sf::IntRect playButtonRect(object.getPosition().x, object.getPosition().y,
object.getGlobalBounds().width, object.getGlobalBounds().height);
sf::Vector2i pixelPos = sf::Mouse::getPosition(window);
sf::Vector2f worldPos = window.mapPixelToCoords(pixelPos);
sf::Vector2i fPos(worldPos.x, worldPos.y);
if (playButtonRect.contains(fPos))
{
return true;
}
}
return false;
}
aby sprawdzać czy kliknięto grafikę, a wewnątrz używam
mapPixelToCoords(sf::Vector2i);
dzięki czemu nawet po zmianie rozmiaru okna kliknięcia są poprawnie wykrywane.
Jednak nie mam pojęcia w jaki sposób wykrywać, który wiersz i kolumnę kliknięto.
Tutaj fragment kodu z tutoriala dotyczącego tworzenia TicTacToe w SFML
// pozycja myszki wzgledem okna aplikacji
sf::Vector2i touchPoint = this->m_data->input.getMousePosition(this->m_data->window);
// prostokąt planszy
sf::FloatRect gridSize = m_gridSprite.getGlobalBounds();
// wolna przestrzeń po lewej i prawej stronie planszy
sf::Vector2f gapOutsideOfGrid = sf::Vector2f((SCREEN_WIDTH - gridSize.width) / 2, (SCREEN_HEIGHT - gridSize.height) / 2);
// pozycja myszki względem planszy
sf::Vector2f gridLocalTouchPos = sf::Vector2f(touchPoint.x - gapOutsideOfGrid.x, touchPoint.y - gapOutsideOfGrid.y);
// pojedynczy kwadrat planszy
sf::Vector2f gridSectionSize = sf::Vector2f(gridSize.width / 3, gridSize.height / 3);
int column, row;
// sprawdzenie, na którą kolumnę kliknął gracz
if (gridLocalTouchPos.x < gridSectionSize.x) // pierwsza kolumna
{
column = 1;
}
else if (gridLocalTouchPos.x < gridSectionSize.x * 2) // druga kolumna
{
column = 2;
}
else if (gridLocalTouchPos.x < gridSize.width) // trzecia kolumna
{
column = 3;
}
// sprawdzenie, na który wiersz kliknął gracz
if (gridLocalTouchPos.y < gridSectionSize.y) // pierwszy wiersz
{
row = 1;
}
else if (gridLocalTouchPos.y < gridSectionSize.y * 2) // drugi wiersz
{
row = 2;
}
else if (gridLocalTouchPos.y < gridSize.height) // trzeci wiersz
{
row = 3;
}
Wszystko fajnie, zrozumiale i w ogóle.
Tylko jak teraz to przerobić żeby po resizie okna wszystko działało ok? I to w dodatku jak moja plansza ma obwódkę?
Próbowałem używać
sf::FloatRect gridSize = sprite.getGlobalBounds();
oraz
sf::FloatRect gridSize = sprite.getLocalBounds();
ale zawsze zwraca mi rozmiar startowy mojego sprite, a nie jego faktyczny rozmiar po resizie. Czy jest na to w ogóle jakiś sposób?
Będę bardzo wdzięczny za każdą poradę.