• 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]

0 głosów
148 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 VIP (105,820 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 VIP (105,820 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 VIP (105,820 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 VIP (105,820 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 VIP (105,820 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ź 481 wizyt
pytanie zadane 30 stycznia 2018 w Sieci komputerowe, internet przez Błażej Gonczar Obywatel (1,630 p.)
0 głosów
0 odpowiedzi 80 wizyt
pytanie zadane 3 maja 2018 w C i C++ przez ___Shell___ Nowicjusz (180 p.)
0 głosów
1 odpowiedź 118 wizyt
pytanie zadane 2 maja 2018 w C i C++ przez Emil Panecki Bywalec (2,110 p.)
Porady nie od parady
Publikując kody źródłowe korzystaj ze specjalnego bloczku koloryzującego składnię (przycisk z napisem code w edytorze). Nie zapomnij o ustawieniu odpowiedniego języka z rozwijanego menu oraz czytelnym formatowaniu kodu.Przycisk code

65,654 zapytań

112,282 odpowiedzi

236,928 komentarzy

46,645 pasjonatów

Przeglądających: 160
Pasjonatów: 0 Gości: 160

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.

...