tBane Temat założony przez niniejszego użytkownika |
Relatywne Pozycjonowanie Elementów » 2026-01-23 16:25:33 Witam. Szukam sposobu na relatywne pozycjonowanie prostokątów w SFML 3.0.2. Chodzi o to, że jak nakładam prostokąt na prostokąt, to żeby one się rozłożyły odpowiednio na siatce, tak jak na załączonym obrazku. Oczywiście szukam uniwersalnego sposobu dla wielu takich prostokątów, ponieważ w moim programie jest wiele okienek. Nakierujecie mnie jak to zrobić?   Chodzi o to by ułożyć poniższe okna:  w taki sposób:  |
|
pekfos |
» 2026-01-23 17:53:39 Weź wszystkie okienka które przecinają się z prostokątem tego zarządzanego obszaru, posortuj je po pozycji Y i ustaw. Na tym realnym przykładzie widać wyraźnie że to ma działać w jednym wymiarze i wszystkie okienka są wyrównane do prawej. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2026-01-23 19:23:56 Ok. A jakby chciał zrobić tak, że okna się do siebie przyklejają z dowolnej strony a nie tylko z prawej, to jak to zrobić i to w sposób animowany oczywiście tzn. Rect::setPosition() co daną jednostkę czasu.
Jak na razie wiem, że trzeba wyznaczyć kąt pod którym jest dane okno względem okna do którego się przykleja i stopniowo zmieniać pozycję okna. Zależy mi na tym, by okno było doklejone albo do okna, albo do krawędzi ekranu. |
|
skovv |
» 2026-01-23 21:20:06 No pytasz o szerszy temat - i tu wszystko zależy od tego co Ty sobie wymyślisz i ustalisz - tak musisz to napisać. Jak chcesz żeby np przyklejały się okna do siebie z danej strony no to musisz stworzyć listę elementów, ich pozycja aktualna i docelowa(wyliczona) a potem według danego odcinka czasu wyliczyć procent animacji i nadawać pozycję okienkom coś typu [x = startowax+(roznicax*procent)]. Trzymaj sobie tylko zmienną określającą do której strony ma wyrównywać i według tej zmiennej obliczaj pozycje docelowe i różnicę start/docelowo |
|
tBane Temat założony przez niniejszego użytkownika |
» 2026-01-23 21:23:50 Mhm.. no dobra... Napiszę kod, podam i zobaczymy co i gdzie poprawić. |
|
skovv |
» 2026-01-23 21:32:08 No to jest tak: - napisz klasę sekcji, w niej trzymaj liste elementów na niej i jej rect. Każdej sekcji nadawaj także osobno wartość zmiennej z ktorej strony ma wyrownywac.. wtedy mozesz dac sekcje lewej i prawej strony ekranu przykladowo, lewa sekcja rowna do lewej strony ekranu, prawa do prawej.. - masz jakąś tam klasę elementu(okna) to ją trzymaj na liście sekcji. Dodaj sobie zmienną bool przeniesiono(zmieniaj na true jeśli właśnie stworzone albo przeniesione), uchwyt na instancje klasy sekcji do ktorej nalezymy i zmienne do animacji okna typu czasAnimacji, startX, celX, procent czy jak ty To siebie tam przesuwasz.. Jeśli przeniesiono to ustawiaj uchwyt na sekcje, licz pozycje docelową w sekcji i oblicz pozycję celX/Y, czasAnimacji na 0 bo dopiero zaczynasz i no.. takie o - pewnie masz w jednym miejscu obsluge wsdzystkich okienek to żeby nie ogarniać teraz wszystkiego osobno to możesz trzymać listę uchwytów do okienek na globalnej liście prócz w sekcjach |
|
tBane Temat założony przez niniejszego użytkownika |
» 2026-01-23 22:46:18 Dobra. Mam :-) Napisałem klasę Rect i Section. Rect to jak wiadomo prostokąt symulujący okno dialogowe, a Section to rect po prawej stronie pozycjonujący recty. Napisałem tak sekcję, że pozycjonuje prostokąty w zależności gdzie są układane w osi Y. Tak wiec można wstawiać na początek, na koniec i gdzieś po środku. Sprawdzi ktoś poprawność mojego kodu?  #include <SFML/Graphics.hpp>
class Rect { public: const static int rectWidth = 128; const static int rectHeight = 64; sf::IntRect _rect; sf::Color _color; bool _isMoved; sf::Vector2i _offset; Rect() { _rect.size.x = rectWidth; _rect.size.y = rectHeight; _color = sf::Color::Green; _isMoved = false; _offset = sf::Vector2i( 0, 0 ); } void setPosition( sf::Vector2i position ) { _rect.position = position; } void draw( sf::RenderWindow & window ) { sf::RectangleShape rect; rect.setSize( sf::Vector2f( _rect.size ) ); rect.setFillColor( _color ); rect.setPosition( sf::Vector2f( _rect.position ) ); window.draw( rect ); } };
class SectionRight { public: const static int margin = 16; sf::IntRect _rect; std::vector < std::shared_ptr < Rect >> _relativeRects; SectionRight() { _rect.size.x = Rect::rectWidth + 2 * margin; _rect.size.y = 600; _rect.position.x = 800 - _rect.size.x; _rect.position.y = 0; } bool contains( sf::Vector2i point ) { return _rect.contains( point ); } bool contains( std::shared_ptr < Rect > rect ) { return std::find( _relativeRects.begin(), _relativeRects.end(), rect ) != _relativeRects.end(); } void positionRects() { for( int i = 0; i < _relativeRects.size(); ++i ) { sf::Vector2i newPosition( _rect.position.x + margin, _rect.position.y + margin + i *( Rect::rectHeight + margin ) ); _relativeRects[ i ]->setPosition( newPosition ); } } void insertRect( std::shared_ptr < Rect > rect ) { auto it = std::find( _relativeRects.begin(), _relativeRects.end(), rect ); if( it != _relativeRects.end() ) { _relativeRects.erase( it ); } int i = 0; int mouseY = rect->_rect.position.y; while( i < _relativeRects.size() && mouseY > _relativeRects[ i ]->_rect.position.y ) { i++; } _relativeRects.insert( _relativeRects.begin() + i, rect ); positionRects(); } void addRect( std::shared_ptr < Rect > rect ) { if( contains( rect ) ) { insertRect( rect ); return; } int i = 0; while( i < _relativeRects.size() && rect->_rect.position.y > _relativeRects[ i ]->_rect.position.y ) { i += 1; } _relativeRects.insert( _relativeRects.begin() + i, rect ); positionRects(); } void removeRect( std::shared_ptr < Rect > rect ) { auto it = std::find( _relativeRects.begin(), _relativeRects.end(), rect ); if( it != _relativeRects.end() ) { _relativeRects.erase( it ); } positionRects(); } void draw( sf::RenderWindow & window ) { sf::RectangleShape rect; rect.setSize( sf::Vector2f( _rect.size ) ); rect.setFillColor( sf::Color::Color( 47, 47, 47 ) ); rect.setPosition( sf::Vector2f( _rect.position ) ); window.draw( rect ); } };
std::vector < std::shared_ptr < Rect >> relativeRects;
std::shared_ptr < Rect > pressedRect( sf::Vector2i cursorPosition ) { for( auto & rect: relativeRects ) { if( rect->_rect.contains( cursorPosition ) ) { return rect; } } return nullptr; }
int main() { sf::RenderWindow window( sf::VideoMode( sf::Vector2u( 800, 600 ), 32 ), "Relative Rects" ); relativeRects.push_back( std::make_shared < Rect >() ); relativeRects.push_back( std::make_shared < Rect >() ); relativeRects.push_back( std::make_shared < Rect >() ); relativeRects.push_back( std::make_shared < Rect >() ); relativeRects[ 2 ]->_color = sf::Color::Red; relativeRects[ 3 ]->_color = sf::Color::Blue; for( int i = 0; i < relativeRects.size(); i += 1 ) { sf::Vector2i position( 32,( Rect::rectHeight + 16 ) * i ); relativeRects[ i ]->setPosition( position ); } std::shared_ptr < SectionRight > sectionRight = std::make_shared < SectionRight >(); sf::Vector2i cursorPosition( 0, 0 ); while( window.isOpen() ) { while( const std::optional event = window.pollEvent() ) { cursorPosition = sf::Mouse::getPosition( window ); if( event->is < sf::Event::Closed >() ) window.close(); if( const auto mouseRelease = event->getIf < sf::Event::MouseButtonReleased >() ) { for( auto & rect: relativeRects ) { if( rect->_isMoved ) { if( sectionRight->contains( rect->_rect.position + rect->_rect.size / 2 ) ) { sectionRight->addRect( rect ); } else { sectionRight->removeRect( rect ); } rect->_isMoved = false; rect->_offset = sf::Vector2i( 0, 0 ); } } } if( const auto mouseClick = event->getIf < sf::Event::MouseButtonPressed >() ) { sf::Vector2i cursorPosition = mouseClick->position; auto rect = pressedRect( cursorPosition ); if( rect ) { rect->_isMoved = true; rect->_offset = cursorPosition - sf::Vector2i( rect->_rect.position ); } } } for( auto & rect: relativeRects ) { if( rect->_isMoved ) { rect->setPosition( cursorPosition - rect->_offset ); } } window.clear(); sectionRight->draw( window ); for( auto & rect: relativeRects ) { rect->draw( window ); } window.display(); } return 0; }
|
|
skovv |
» 2026-01-24 00:21:45 Jak działa to poprawny, uwierz w siebie w końcu :D |
|
| « 1 » 2 |