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

SFML - umieszczanie obiektów liczących czas (sf::Clock i innych ) jako składowe klasy, czy to przejdzie?

Object Storage Arubacloud
0 głosów
271 wizyt
pytanie zadane 12 lipca 2018 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)

Witam, tworzę gierkę polegającą na omijaniu spadających z góry przeszkód:

Wiele razy potrzeba jest tu liczyć i przechowywać czas, trzeba obliczać czas do zmiany kolorów obiektów i tła ( bo po czasie dla urozmaicenia rozgrywki grafika lekko się zmienia ), co losowy czas generowani są nowi przeciwnicy. Czas do nowej generacji jest losowany i przechowywany w odpowiedniej zmiennej, potem trzeba też go liczyć obiektem sf::Clock. Ponieważ zmianami na mapie zajmują się odpowiednie funkcje ( wywoływane w pętli gry ) to wspomniane wartości nie mogą być przechowywane przez zmienne automatyczne - wobec tego muszą być one statyczne w tych funkcjach. Tak też początkowo było... jednak dodałem nowy stan programu jakim jest menu główne, a ponieważ pamięć zmiennych statycznych istnieje przez cały okres działania programu to po wybraniu w menu ponownej rozgrywki były oczywiście niechciane efekty uboczne ( zmienne powinny zostać wtedy wyzerowane ). By istniały one przez cały okres trwania rozgrywki a zostały zwolnione po jej zakończeniu to nadałem im zasięg klasy, oto kilka z nich:

Czy umieszczanie jednak zmiennych pełniących rolę jakiś timerów w grze jako składowych klasy jest mądre? Może powinienem w inny sposób je przechowywać, w specjalnych strukturach czy coś...?

 

Będę bardzo wdzięczny za doradzenie mi czy zastosowane tu podejście jest znośnie ;)

1 odpowiedź

+1 głos
odpowiedź 12 lipca 2018 przez criss Mędrzec (172,590 p.)

a ponieważ pamięć zmiennych statycznych istnieje przez cały okres działania programu to po wybraniu w menu ponownej rozgrywki były oczywiście niechciane efekty uboczne ( zmienne powinny zostać wtedy wyzerowane ).

Fajnie jakby każdy stan miał jakąś metode w stylu onStart() w której będzie się dziać inicjalizacja za każdym razem kiedy stan jest uruchamiany. 

A timer najlepiej jakby był jeden na całą apke (w mainie czy głownej klasie) a do niższych warstw przekazywana była tylko wartość delta time, to w zupełności wystarczy i wszystkie obiekty będą się poruszały (czy wykonywały inne czynności bazujące na czasie) jednolicie na podstawie jednej wartości delta time (co nie jest do końca prawdą gdy każdy obiekt ma swój własny timer).

komentarz 12 lipca 2018 przez Jakub 0 Pasjonat (23,120 p.)

Dziękuje za odpowiedź, 

Fajnie jakby każdy stan miał jakąś metode w stylu onStart()

No ale przecież konstruktor jest do takich rzeczy. Nie za bardzo rozumiem po co taka metoda :/ Po za tym u mnie każdy stan jest przydzielany dynamicznie a stary jest zwalniany:

void Program::run() {

	while (m_window.isOpen()) {

		StatesReturns sig = m_states->loop(m_window);

		if (sig.signals == Signals::EXIT) {
			delete m_states;
			m_window.close(); 
		}

		else if (sig.signals == Signals::GAME) {
			delete m_states; 
			m_states = new GameStates(sf::Vector2u(m_window.getSize().x, m_window.getSize().y));
		}

		else if (sig.signals == Signals::MENU) {
			delete m_states;
			m_states = new MenuStates(); 
		}

		else if (sig.signals == Signals::GAMEOVER) {
			delete m_states;
			m_states = new GameOverStates(sf::Vector2u(m_window.getSize().x, m_window.getSize().y), sig.additionalValue);
		}

		else if (sig.signals == Signals::NONE) {
			delete m_states; 
			std::cout << "Fatal Error!\n";
			system("pause");
			m_window.close(); 
		}
	}

A timer najlepiej jakby był jeden na całą apke (w mainie czy głownej klasie) a do niższych warstw przekazywana była tylko wartość delta time

Podoba mi się to, ale mam kilka wątpliwości:

1. Jeżeli program będzie działał długo to czy przechowywany w timerze upłynięty czas nie będzie zbyt duży. 

2. Dzięki temu nie będę musiał tworzyć wielu liczników ( timerów dla różnych zdarzeń ), ale nie uniknę innych problemów, np:

int delayToNewOpponentGenerate = 0; //temp static info 

Tu będzie trafiać wybrany losowo czas do generowania nowych bloków, gdzieś tą zmienną trzeba przechować i wyzerować po zniszczeniu obiektu więc nie może być statyczna. Nie jest to też timer. ( więc bałaganu w klasie całkiem nie uniknę )

komentarz 12 lipca 2018 przez criss Mędrzec (172,590 p.)

No ale przecież konstruktor jest do takich rzeczy. Nie za bardzo rozumiem po co taka metoda :/ 

Skoro czas jest dalej liczny przez state Game podczas gdy aktywny jest state Menu (tak zrozumiałem), to chyba jest potrzebna.

1. Przez timer miałem na myśli sf::Clock.
2. delayToNewOpponentGenerate może być static w klasie skoro jest przecież specyficzną częścią jakiejś klasy. Btw. dlaczego to nie jest float?

komentarz 12 lipca 2018 przez Jakub 0 Pasjonat (23,120 p.)
edycja 12 lipca 2018 przez Jakub 0

Skoro czas jest dalej liczny przez state Game podczas gdy aktywny jest state Menu (tak zrozumiałem), to chyba jest potrzebna.

A nie można odpowiednie właściwości wyzerować po prostu w konstruktorze nowego obiektu stanu? Wtedy jest gwarancja że tego nie zapomnę. Zresztą nie zależnie czy w konstruktorze czy w metodzie musiał bym mieć wskaźnik do zmiennych statycznych które są w zasięgu metod więc zbyt by się to skomplikowało.  Zrobię chyba po prostu jeden główny timer. ( jak była mowa )

Przez timer miałem na myśli sf::Clock.

Wiem, chodziło mi o to że po czasie czas od utworzenia tego obiektu ( czyli właściwie od początku programu ) mógł by być zbyt duży żeby go zmieścić w zmiennej. Ale to już nieaktualne... bo przy nowym stanie programu będzie można go przecież wyzerować.

dlaczego to nie jest float

Wiem że powinien być typu float, tyle że liczby losowe można generować tylko jako typ stałoprzecinkowy, oczywiście można losować czas np. w milisekundach i potem go dzielić przez odpowiednią stałą zamieniając znowu na sekundy. Tak początkowo było, ale miałem wtedy dziwne anomalie... a ponieważ byłem zajęty innymi częściami programu to tymczasowo dałem sobie spokój i losuje wartość całkowitą ( jak na razie taka wystarcza ). Potem oczywiście to zmienię jak uporam się z innymi poważniejszymi problemami projektu ( strukturalnymi, takimi jak teraz ), To tyle na moje usprawiedliwienie ;)

1
komentarz 12 lipca 2018 przez criss Mędrzec (172,590 p.)

1. Zrób jak chcesz. W każdym razie - jak na razie ani nie tworzysz nowego obiektu, ani nie wołasz takie metody. Stąd tylko moja propozycja.
2. Co do losowania - masz przeciez std::uniform_real_distribution i generatory z <random>

komentarz 13 lipca 2018 przez Jakub 0 Pasjonat (23,120 p.)

1. No właśnie, coś mi przyszło na myśl:

Może być co prawda jeden główny obiekt sf::Clock dla programu, ale dalej potrzebuje znać czas zaczęcia odliczania, przykład dla liczenia czasu klatki:

deltaTime = FrameTime.getElapsedTime().asSeconds() - frameStart;

Dalej będę musiał mieć pewne zmienne statyczne w metodach ( które będą musiały być wyzerowane po zakończeniu stanu gry czy jakiegokolwiek innego ) lub uniknąć problemów sprawiając by były po prostu składowymi klasy.

Od nośnie pomysłu z metodą onStart() lub zwykłym konstruktorem nowego obiektu który miał by pewne zmienne statyczne wyzerować, czy trzeba było by wziąć na nie wskaźnik... i moim zdaniem jeszcze bardziej wszystko skomplikować? Czy może mogły by być przechowywane gdzie indziej w programie, to jednak rodzi kolejny problem: nie każdy stan programu będzie potrzebowałem takiego samego zestawu zmiennych. Może po prostu zostawić takie zmienne jako składowe klasy ?

*edit: a może by te zmienne umieścić w pętli gry ( danej klasy stanu ) a nie jako statyczne w metodach ich używających? Potem byś my te zmienne tylko przekazywali jako argument do tych metod.

2. Dziękuje za info, co prawda znam znam angielski i c++ na tyle żeby w miarę  rozumieć te dokumentacje i poszukiwać informacji, nie wiem czemu tego nie zrobiłem. Założyłem że raczej takie rzeczy trzeba samemu zaimplementować.

komentarz 13 lipca 2018 przez criss Mędrzec (172,590 p.)

Może po prostu zostawić takie zmienne jako składowe klasy ?

Ja bym tak zrobił. Najprostsze pomysły są często najlepsze. Statyczne w funkcji moim zdaniem tylko gdy taka zmienna jest używana przez tą funkcję.

komentarz 13 lipca 2018 przez Jakub 0 Pasjonat (23,120 p.)

Statyczne w funkcji moim zdaniem tylko gdy taka zmienna jest używana przez tą funkcję.

Nie rozumiem zdania :/ Przecież właśnie po to tworzy się zmienne by były przez funkcje/metody używane.  Te zmienne też są tworzone z myślą o odpowiednich metodach.

komentarz 13 lipca 2018 przez Jakub 0 Pasjonat (23,120 p.)
Widzę że coś się źle zrozumieliśmy ;)
komentarz 13 lipca 2018 przez criss Mędrzec (172,590 p.)

Miało być " Statyczne w funkcji moim zdaniem tylko gdy taka zmienna jest używana tylko przez tą funkcję", sorry :P

Podobne pytania

0 głosów
0 odpowiedzi 250 wizyt
+1 głos
1 odpowiedź 233 wizyt
pytanie zadane 5 sierpnia 2020 w C i C++ przez NieMaJuzNazw Użytkownik (890 p.)

92,583 zapytań

141,434 odpowiedzi

319,669 komentarzy

61,966 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy 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!

...