• 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

0 głosów
106 wizyt
pytanie zadane 10 lipca 2018 w C i C++ przez Matematyk0606 Bywalec (2,770 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 (204,320 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 Matematyk0606 Bywalec (2,770 p.)
Czyli chcesz mi powiedzieć, że dwa obiekty Event mogą przetrzymywać dwa różne zdarzenia?
komentarz 10 lipca 2018 przez adrian17 Ekspert (204,320 p.)
Nie rozumiem pytania. Mówię, że drugie pollEvent() nic nie robi.
komentarz 10 lipca 2018 przez Matematyk0606 Bywalec (2,770 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 (204,320 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 Matematyk0606 Bywalec (2,770 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 (204,320 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 Matematyk0606 Bywalec (2,770 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ź 93 wizyt
pytanie zadane 22 marca 2018 w C i C++ przez Perseusz Bywalec (2,210 p.)
0 głosów
1 odpowiedź 217 wizyt
0 głosów
2 odpowiedzi 265 wizyt
Porady nie od parady
Odznacz odpowiedź zieloną fajką, jeśli uważasz, że jest ona najlepsza ze wszystkich i umożliwiła ci rozwiązanie problemu.Najlepsza odpowiedź

67,116 zapytań

114,064 odpowiedzi

241,764 komentarzy

47,028 pasjonatów

Przeglądających: 184
Pasjonatów: 10 Gości: 174

Motyw:

Akcja Pajacyk

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

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...