• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Nie działają jednocześnie dwa bloki kodu "while (window->pollEvent(event))" ustawione pod sobą - C++ SFML 2.4

VPS Starter Arubacloud
0 głosów
446 wizyt
pytanie zadane 10 lipca 2018 w C i C++ przez DarkEliat Bywalec (2,810 p.)

Witam.

Pracuję nad kodem Drag&Drop (Moje poprzednie pytanie: https://forum.pasja-informatyki.pl/346053/nie-dziala-kod-zlap-przeciagnij-pusc-c-sfml jeśli ktoś ma jakiś inny pomysł jak rozwiązać ten problem będę wdzięczny za odpowiedź).

Próbuję użyć Eventów w dwóch miejscach w kodzie, ale jak się okazuje działa tylko ten ustawiony na samym początku pętli głównej gry.

Taki zapis dział, ale nijak nie mi jest pomocny:

while (window->isOpen() && gameInfo->state == GameInfo::GAME)
		{
			sf::Event event;
			while (window->pollEvent(event))
			{
				if (event.type == Event::KeyPressed && event.key.code == Keyboard::Escape)
					window->close();
				if (event.type == Event::Closed)
					window->close();
				if (event.type == Event::LostFocus)
					paused = true;

				switch (event.type)
				{
					case Event::MouseButtonPressed:
						if (event.mouseButton.button == Mouse::Left)
						{
							cout << "START ";
						}
						break;

					case Event::MouseButtonReleased:
						if (event.mouseButton.button == Mouse::Left)
						{
							cout << "STOP ";
						}
						break;
					}
			}
// ...

Co ciekawe taki zapis nie działa (poprawnie wykonuje się tylko pierwsza pętla pollEvent):

while (window->isOpen() && gameInfo->state == GameInfo::GAME)
		{
			sf::Event event1;
			while (window->pollEvent(event1))
			{
				switch (event1.type)
				{

				case Event::MouseButtonPressed:
					if (event1.mouseButton.button == Mouse::Left)
					{
						cout << "START ";
					}
					break;

				case Event::MouseButtonReleased:
					if (event1.mouseButton.button == Mouse::Left)
					{
						cout << "STOP ";
					}
					break;
				}
			}

			sf::Event event;
			while (window->pollEvent(event))
			{
				if (event.type == Event::KeyPressed && event.key.code == Keyboard::Escape)
					window->close();
				if (event.type == Event::Closed)
					window->close();
				if (event.type == Event::LostFocus)
					paused = true;

				
			}
// ...

Co jeszcze ciekawsze taki zapis działa, ale także jest totalnie bezużyteczny, ponieważ blokuje wykonywanie całego programu:

while (window->isOpen() && gameInfo->state == GameInfo::GAME)
		{
			sf::Event event1;
			while (window->pollEvent(event1))
			{
				switch (event1.type)
				{

				case Event::MouseButtonPressed:
					if (event1.mouseButton.button == Mouse::Left)
					{
						cout << "START ";
					}
					break;

				case Event::MouseButtonReleased:
					if (event1.mouseButton.button == Mouse::Left)
					{
						cout << "STOP ";
					}
					break;
				}
			}

			while (window->isOpen() && gameInfo->state == GameInfo::GAME)
			{
				sf::Event event;
				while (window->pollEvent(event))
				{
					if (event.type == Event::KeyPressed && event.key.code == Keyboard::Escape)
						window->close();
					if (event.type == Event::Closed)
						window->close();
					if (event.type == Event::LostFocus)
						paused = true;


				}
			}
// ...

Jest mi to w stanie ktoś wytłumaczyć? Byłbym bardzo wdzięczny za radę jak korzystać z kilku pętli "while (window->pollEvent(event))" na raz. Dodam jeszcze, że ta druga będzie się znajdowała w innym pliku.

Pozdrawiam.

1 odpowiedź

0 głosów
odpowiedź 10 lipca 2018 przez adrian17 Ekspert (344,100 p.)

Co ciekawe taki zapis nie działa (poprawnie wykonuje się tylko pierwsza pętla pollEvent):

Co ma sens - ten kod nie ma prawa działać.

            sf::Event event1;
            while (window->pollEvent(event1))

Pierwsza pętla wywołuje się tak długo, jak (while) są jeszcze jakieś nieobsłużone eventy. pollEvent() ściąga je z wewnętrznej kolejki eventów i przekazuje Tobie. Po zakończeniu tej pętli...

            sf::Event event2;
            while (window->pollEvent(event2))

Nie ma już żadnych nieobsłużonych eventów (dlatego poprzednia pętla while się skończyła), więc pollEvent() nie przekaże ani jednego eventu, więc ta pętla nie wykona się ani razu.

Byłbym bardzo wdzięczny za radę jak korzystać z kilku pętli "while (window->pollEvent(event))"

Musisz mieć jedno centralne miejsce wyciągające eventy (choć niekoniecznie w jednym przez całość działania programu) - te eventy możesz przekazywać i obsługiwać gdziekolwiek chcesz. Może być na przykład coś w stylu

while (window->pollEvent(event))
{
	ui->handleEvent(event);
	world->handleEvent(event);
	playerEntity->handleEvent(event);
    // etc etc
}

 

komentarz 10 lipca 2018 przez DarkEliat Bywalec (2,810 p.)
Czyli chcesz mi powiedzieć, że dwa obiekty Event mogą przetrzymywać dwa różne zdarzenia?
komentarz 10 lipca 2018 przez adrian17 Ekspert (344,100 p.)
Nie rozumiem pytania. Mówię, że drugie pollEvent() nic nie robi.
komentarz 10 lipca 2018 przez DarkEliat Bywalec (2,810 p.)
Bo napisałeś, że je można przekazywać, stąd moja myśl, że jeśli gdzieś je wyślę, a za ten czas wydarzy się kolejne zdarzenie, to tamto wysłane dalej będzie miało informację o starym zdarzeniu?

Masz jakiś pomysł jak to okodować?

Ewentualnie jeśli miałbyś pomysł jak rozwiązać problem z pytania do którego dałem link, to zdarzenia byłyby zbędne. Dlatego proszę spojrzyj na nie w wolnej chwili bo to blokuje moje prace.
komentarz 10 lipca 2018 przez adrian17 Ekspert (344,100 p.)

Przekombinowujesz.

W oknie zbiera się kolejka zdarzeń. Przez te kilka milisekund które spędzasz na wyświetlaniu rzeczy lub robieniu jakiejś innej logiki, mogło na przykład przyjść kilka zdarzeń ruchu myszy.

window->pollEvent(event);

Wywołanie pollEvent() ściąga zdarzenie z kolejki do Twojej zmiennej `event`. `event` zawiera teraz informacje o tym zdarzeniu.

Jeśli nie ma żadnych zdarzeń w kolejce, pollEvent() nic nie robi i zwraca false.

Czy w tym widzisz coś konfudującego?

Ewentualnie jeśli miałbyś pomysł jak rozwiązać problem z pytania do którego dałem link, to zdarzenia byłyby zbędne. Dlatego proszę spojrzyj na nie w wolnej chwili bo to blokuje moje prace.

To pytanie sprzed 3 miesięcy, na które dostałeś rozsądnie wyglądającą odpowiedź. Nie rozumiem tez, co to pytanie ma do "kilku pętli pollEvent".

komentarz 10 lipca 2018 przez DarkEliat Bywalec (2,810 p.)
To w sumie prawda odnośnie tej odpowiedzi, ale musiałem przebudować ten kod. Mnie też się wydawało, że jest dobry (może jest, ale ja mogę nie potrafić go użyć). Ten kod od użytkownika j23 musiałem umieścić w osobnym pliku (klasie), a później okazało się, że takie rozwiązanie nie działa. Właśnie dlatego potrzebuję 2 pętli.

Albo zrobię to po swojemu jak było w tym pytaniu (tam nie używałem eventów), tylko ktoś musi mi wskazać błąd.
komentarz 10 lipca 2018 przez adrian17 Ekspert (344,100 p.)

Chodzi o drag&drop, tak? Ogólna idea tamtego kodu j23 jest dobra, napisałem coś własnego podstawowego od ręki i wydaje się działać:

https://puu.sh/AUbdE/a652ed181b.mp4

#include <SFML/Graphics.hpp>
int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");

    sf::RectangleShape rect({50, 50});
    rect.setPosition(100, 100);

    sf::Vector2i pos;
    bool dragging = false;

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::MouseButtonPressed:
                    if(event.mouseButton.button == sf::Mouse::Left) {
                        pos = sf::Vector2i(event.mouseButton.x, event.mouseButton.y);
                        if (rect.getGlobalBounds().contains(pos.x, pos.y))
                            dragging = true;
                    }
                    break;
                case sf::Event::MouseButtonReleased:
                    if(event.mouseButton.button == sf::Mouse::Left) {
                        dragging = false;
                    }
                    break;
                case sf::Event::MouseMoved:
                    if(dragging)  {
                        sf::Vector2i pos2(event.mouseMove.x, event.mouseMove.y);
                        sf::Vector2i move = pos2 - pos;
                        rect.move(move.x, move.y);
                        pos = pos2;
                    }
                    break;
            }
        }
        window.clear();
        window.draw(rect);
        window.display();
    }
}

 

komentarz 11 lipca 2018 przez DarkEliat Bywalec (2,810 p.)
Dziękuję za pomoc! Teraz tylko będę musiał przebudować ten kod by działał pod talię (klasa Deck). Boję się, że znów wyniknie jakaś głupia anomalia, podobna do tego co opisałem w tamtym pytaniu (przesuwalność tylko jednej obiektu).

Pozdrawiam.

Podobne pytania

0 głosów
1 odpowiedź 196 wizyt
pytanie zadane 22 marca 2018 w C i C++ przez Perseusz Bywalec (2,190 p.)
0 głosów
1 odpowiedź 556 wizyt
0 głosów
2 odpowiedzi 1,054 wizyt

92,454 zapytań

141,263 odpowiedzi

319,099 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...