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

Przesyłanie pozycji pocisku jako pakiet [TCP]

VPS Starter Arubacloud
0 głosów
448 wizyt
pytanie zadane 16 października 2018 w C i C++ przez żółwibekon Początkujący (300 p.)
edycja 16 października 2018 przez żółwibekon

Cześć, otóż mam pewien problem, mianowicie chciałbym stworzyć przy pomocy SFML grę, w której to dwóch graczy strzela do siebie za pomocą pocisków - kto pierwszy trafi przeciwnika ten wygrywa. Jako że nigdy nie programowałem aplikacji sieciowej to postawiłem przed sobą nie lada wyzwanie.

Z początku sobie poradziłem. Ustanowiłem połączenie oraz poradziłem sobie z wysyłaniem pakietu w przypadku zmiany pozycji drugiego gracza, dzięki czemu bez problemów działa poruszanie się i widać to na obydwu aplikacjach :) Jedyne co mi pozostało to wysyłanie zmiany pozycji pocisku i aktualizowanie go, ale tutaj niestety już nie wiem co jest przyczyną mojego niepowodzenia.

Na początku porwałem się od razu na głęboką wodę i chciałem wysyłać na raz pozycje wszystkich pociski, ale się mocno pogubiłem. Potem żeby spróbować to sobie ogarnąć to ograniczyłem ilość możliwych pocisków do wystrzelenia do 1, dzięki czemu nie ma takiej rozróby, co zobaczycie w kodzie poniżej.

Przechodząc do sedna: pakiet ze zmienną zawierającą nową pozycję pocisku normalnie dociera do gniazda, tylko problem w tym, że gdy przypisuje obiektowi bullet[0] nową pozycję to zamiast pociskowi przypisuje się ona dla gracza, przez co po wciśnięciu lewego przycisku myszy wystrzela się gracz, a nie pocisk frown Może jestem już zmęczony i popełniłem gdzieś głupi błąd, tak czy inaczej proszę o nakierowanie mnie na rozwiązanie problemu i i jakieś cenne wskazówki, bo mam wrażenie, że nie ogarniam programowania sieciowego zbyt dobrze. Cała akcja ma miejsce w metodzie update() w pliku multiplayer.cpp.

multiplayer.hpp
multiplayer.cpp

bullet.cpp

player.cpp

Pozdrawiam

żółwibekon

komentarz 16 października 2018 przez Sheida Użytkownik (950 p.)
Nie działa drugi link, multiplayer.cpp
komentarz 16 października 2018 przez żółwibekon Początkujący (300 p.)
Poprawione
komentarz 16 października 2018 przez j23 Mędrzec (194,920 p.)

Rozumiem, że Multiplayer::update jest dla obu stron, klienta i serwera, tak?

komentarz 16 października 2018 przez żółwibekon Początkujący (300 p.)
przywrócone 16 października 2018 przez żółwibekon
@j23 tak, po prostu odpalam aplikacje 2 razy i w jednym okienku z atrybutem serwer, a w drugim z atrybutem client

1 odpowiedź

0 głosów
odpowiedź 16 października 2018 przez j23 Mędrzec (194,920 p.)
wybrane 21 października 2018 przez żółwibekon
 
Najlepsza
Pierwsze, co mi się rzuciło w oczy to to, że warunkowo wysyłasz pozycję playera i pocisku, ale odbierasz bezwarunkowo. Czyli jeżeli player nie zmieni pozycji, niczego nie wysyłasz, ale druga strona i tak będzie odbierać pozycję gracza, a wtedy odbierze pozycję pocisku. IMO pakiety powinny zawierać info odnośnie tego, co się w nich znajduje i czego dotyczą (ID gracza/pocisku/czegokolwiek).
komentarz 21 października 2018 przez żółwibekon Początkujący (300 p.)

Cześć, odkąd mi to napisałeś przemyślałem to i przerobiłem wysyłanie pakietu dodając dodatkową zmienną w czasie wysyłania, tak by można było odróżnić co znajduje się w danym pakiecie. Co najdziwniejsze, przed tą zmianą jak i po zauważyłem, że mój warunek

if (tpacket >> updatebulletPosition.x >> updatebulletPosition.y >> i)
		std::cout << "received bullet position\n";

nigdy się nie realizuje, i to zarówno gdy dodam dodatkową zmienną jak i usunę, ten if nigdy się nie spełnia i już nie mam pomysłów o co może chodzić, a chciałbym w końcu ruszyć dalej..

A tak to wygląda w przypadku wysyłania pozycji gracza:

if (tpacket >> temp >> updateplayerPosition.x >> updateplayerPosition.y)
		player2->setPosition(updateplayerPosition);

i ten warunek normalnie się spełnia. Mam wrażenie, że te pakiety po prostu ze sobą kolidują, no bo jak to możliwe, że mimo identycznych warunków jeden z nich się nie spełnia?

PS. Sprawdzałem i pakiet z pozycją pocisku w danym momencie wysyła się bez problemu.

komentarz 21 października 2018 przez j23 Mędrzec (194,920 p.)

Pokaż kod metody Multiplayer::update po zmianach.

komentarz 21 października 2018 przez żółwibekon Początkujący (300 p.)
1
komentarz 21 października 2018 przez j23 Mędrzec (194,920 p.)
edycja 21 października 2018 przez j23

Dziwacznie to rozwiązałeś. Tak bym to zrobił:

enum class PacketType:int { playerPos, bulletPos };
...

void Multiplayer::receivePackets()
{
	sf::Vector2f pos;
	sf::Packet packet;
	int type;

    socket.receive(packet);

	if(packet >> type)
	{
		switch(type)
		{
			case PacketType::playerPos:
				if(packet >> pos.x >> pos.y)
				{
					player2->setPosition(pos);
				}
				break;

			case PacketType::bulletPos:
				if(packet >> pos.x >> pos.y)
				{
					std::cout << "received bullet position\n";
				}
				break;
		}
	}
}

Wysyłasz w takiej samej kolejności: typ, x i y.

komentarz 21 października 2018 przez żółwibekon Początkujący (300 p.)
Piękny pomysł i fajnie to wygląda, od razu wdrożyłem to w projekt :) Tylko teraz jest na odwrót, tj. nie można z pakietu odczytać pozycji gracza, natomiast pozycja pocisku zostaje odczytana i warunek się spełnia.

https://pastebin.com/vmcMaRmK

PS. Z tego co zauważyłem to warunek w switchu z pozycją gracza się spełnia, tylko nie wiem dlaczego nie przypisuje nowej pozycji dla gracza, jestem już zmęczony i problem jest pewnie trywialny..
komentarz 21 października 2018 przez żółwibekon Początkujący (300 p.)
edycja 21 października 2018 przez żółwibekon

Rozwiązałem problem ze wszystkim co napisałem w komentarzu powyżej. Wystarczyło utworzyć obiekt klasy sf::Packet w pliku nagłówkowym zamiast w metodzie update(). Nie wiem co mam powiedzieć, bardzo mocno Ci dziękuje za pomoc j23. Jednak mam jeszcze jedno pytanie do Ciebie, czy mógłbyś mi wytłumaczyć dlaczego mój sposób powyżej nie działał prawidłowo, natomiast Twój zadziałał bez problemu? Chciałbym z tego wyciągnąć jakąś lekcję.

1
komentarz 21 października 2018 przez j23 Mędrzec (194,920 p.)
Czytanie z pakietu jest strumieniowe, czyli jak już coś przeczytasz operatorem >>, to drugi raz tego nie przeczytasz. W pierwszym warunku czytałeś trzy wartości, bez rozróżnienia czy wartości są dla playera czy pocisku, no to siłą rzeczy w drugim warunku nie mogłeś nic przeczytać z pakietu, bo już nie było danych. I dlatego drugi warunek nie przechodził.

Podobne pytania

0 głosów
1 odpowiedź 684 wizyt
pytanie zadane 30 stycznia 2018 w Sieci komputerowe, internet przez niezalogowany
0 głosów
1 odpowiedź 297 wizyt
pytanie zadane 22 kwietnia 2022 w C# przez muzyk Użytkownik (860 p.)
+2 głosów
0 odpowiedzi 112 wizyt

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,853 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!

...