Skocz do zawartości

Ping - Pong Multiplayer.


Rekomendowane odpowiedzi

A więc wziąłem się do napisanie tego oto poradnika :D Poradnik jest na temat stworzenia gry, ping-ponga multiplayer używając do tych celów, Game Maker'a, a także 39DLL.

Będą nam potrzebne:

- 39DLL - Do pobrania

- Game Maker PRO - Do kupienia na GMC

- Cierpliwość :D - Rzecz nie do kupienia

Zaczynajmy:

Pierwszą rzeczą którą musi zrobić jest zaimportowanie skryptów 39DLL. Jest to łatwe do zrobienia, klikamy "File" i z menu wybieramy "Merge game...". W okienku które wyskoczy szukamy pliku "DLLScripts.gmk" który znajduje się w folderze z DLL'em. Po zrobieniu tego musimy przygotować sprit'y, potrzebujemy:

- paletki,

- piłki,

- przycisku "join",

- przycisku "host",

- pionowej lini.

Tworzymy pokój i nazywamy go "RMMenu", teraz otwieramy go, klikamy na zakładke "settings", a tam, na dole "Cration Code.". Wpisuje tam taki oto kod:

GML
dllinit(0,true,false) //0 - oznacza ze DLL nazywa sie 39dll.dll i znajduje sie w folderze z gra, pierwsze true oznacza zaladowanie funkcji socketow, a false oznacza nie zaladowanie funkcji plikow</span></span></span></span>

Ten kod służy do inicjacji naszego DLL. Musi być wykonany, po to abyśmy mogli używać jego funkcji. Czyli ta funkcja musi być wykonana jako pierwsza. Oczywiście jeżeli ktoś chce może załadować funkcje do operacji na plikach, ale w tak prostej grze nie jest to potrzebne. Teraz kolejna ważna rzecz, dołączanie do servera. Oto kod który należy wkleić w przycisku "join", w evencie "Mouse"->"Left Released".

GML
ip = get_string("Podaj IP do ktorego chcesz sie polaczyc:", "127.0.0.1"); //Pytamy o IP

global.otherplayer = tcpconnect(ip, 14804, 1); //Laczymy sie z danym serverem pod portem 14804

if(!global.otherplayer) //Jezeli false...

{

show_message("Nie mozna polaczyc z serverem."); //...pokazujemy wiadomosc

exit;//i wychodzimy z akcji

}

else //innaczej

global.host = false; //Zmienna mowi ze nie hostujemy

room_goto(RMGame); //Idziemy grac</span></span></span></span>

Musisz stworzyć pokój "RMGame" gdzie będzie można grać :P Przy okazji stwórz także pokój o nazwie "RMHost", gdzie hoster będzie czekał na gracza. Stwórz obiekt, w którym po kliknięciu lewym przyciskiem myszki przeniesie nas do pokoju o nazwa "RMHost". Teraz utwórz nowy obiekt, które będzie odpowiadał za oczekiwanie hostera na gracza. W tym obiekcie dodaj:

Create

GML
listen = tcplisten(14804, 2, 1); //Nasluchujemy na porcie 14804, na polaczenie. 2 oznacza ilosc graczy

global.host = true; //Zmienna okreslajaca iz hostujemy</span></span></span></span>

Step

GML
sock = tcpaccept(listen, 1); //Akceptujemy polaczenia

if(sock) //Jezeli jakies jest

{

closesocket(listen); //Zamykamy socket na ktorym nasluchujemy

global.otherplayer = sock; //Bedziemy wysylac dane do osoby ktora sie polaczyla

room_goto(RMGame); //Idziemy grac

}

Ewentualnie, można dodać w Draw:

GML
draw_text(0, 0, "Czekam na gracza..."); //Piszemy tekst na pozycji x= 0, y= 0</span></span></span></span>

To wszystko odpawiada za oczekiwanie hostera na gracza, sporo :P

Kolejnym krokiem jest stworzenie obiektu które będzie blokował piłeczke aby za daleko nie wypadła.

Ustaw mu solid, a następnie sprite "pionowej lini". Ten obiekt musi stać w górnej i dolnej stronie pokoju "RMGame".

Czasz na piłeczke, trudna sprawa... <joke> Tak naprawde piłka nie jest taka trudna. Wystarczy odpowiednio wysyłać jej pozycje x i y. W create piłeczki:

GML
if(global.host) //jesli hostujemy

{

direction = random(360); //random direction

speed = 8; //predkosc

setnagle(global.otherplayer, true) //To zapobiega lagom, należy to wstawić przed rozpoczęciem gry, bardzo się opłaca

}

Step:

GML
if(global.host) //Jesli hostujemy...

{

clearbuffer();//...czyscimy bufor, musi odbyc sie przed kazdym wyslaniem wiad.

writebyte(1); //ID wiadomosci, aby gracz, wiedzial co ma odebrac

writeshort(x);//wysylamy X pilki

writeshort(y);//wysylamy Y pilki

sendmessage(global.otherplayer); //Wysylamy, do gracza

}

Do wysyłania możemy użyć także tych funkcji:

GML
writebyte( wartosc );//Wysyla 1 bajt, wartosc pomiedzy 0 a 255

writeshort( wartosc );//Wysyla 2 bajtowa wartosc liczbowa, z przedzialu -32768 a 32767

//Jezeli chcemy wyslac wieksze lub mniejsze liczby uzywamy tych funkcji:

writeint( wartosc );

//Lub

writedouble( wartosc );

 

writestring( string ); //Wysyla ciag znakow(string)</span>

Kolizje z paletką, i obramowaniem to nic innego jak zwykłe odbicie. A outside room:

GML
x = xstart

y = ystart

Mamy już piłeczke, ale co teraz? Teraz pora na paletki, każdej zawartość będzie inna, po to abyśmy nie sterowali obiema, tylko jedną, a także dla wielu innych rzeczy. Paletka gracza pierwszego, czyli ta którą gra hoster. Jej zawartość:

- Destroy

GML
closesocket(global.otherplayer); //Zamykamy socket

room_goto(RMMenu); //Wracamy do menu</span></span></span></span>

- Step

GML
if(!global.host)exit;

while(1) //Petla while

{

size = receivemessage(global.otherplayer); //Odbieramy wiad.

if(size < 0)break; //Wylamujemy z petli, gdy napotka blad

if(size == 0) //Jezeli nic nie ma :(

{

show_message("Drugi gracz opuscil gre."); //Pokazujemy wiadomosc

instance_destroy(); //Nisczymy sie

break;

}

mid = readbyte(); //Odczytujemy byte

switch(mid) //Switch

{

case 0:

objPlayer2.y = readshort(); //Odbieramy Y drugiego gracza

break;

 

case 1:

objBall.x = readshort(); //Odbieramy X pilieczki

objBall.y = readshort(); //Odbieramy Y pileczki

break;

}

}

- Strzałka W Góre

GML
if(y > 0 and global.host)

{

y -= 5;

event_user(0);

}

- Strzałka W Dół

GML
if(y + sprite_height < room_height and global.host)

{

y += 5;

event_user(0);

}

Teraz dodaj event User Definied 0 a w nim:

GML
clearbuffer(); //Czyscimy bufor

writebyte(0); //ID wiad. dla ruchu paletki

writeshort(y); //wysylamy pozycje Y

sendmessage(global.otherplayer); //wysylamy</span></span></span></span>

Koniec, jak na razie pierwszej paletki. Przyszła pora na drugą. Jest to prawie to samo, lecz różni się tym, jak już mówiłem wyżej, że sprawdzamy czy jesteśmy hostem, czy nie. No więc nie będe się rozgadywał, bierzmy się do roboty. Kod tej paletki będzie bez komentarzy, ponieważ wszystko w niej to to samo co w pierwszej, a więc wystarczy looknąć wyżej :P

Zaczynajmy, event Destroy:

GML
closesocket(global.otherplayer);

room_goto(RMMenu)

- Step

GML
if(global.host)exit;

while(1)

{

size = receivemessage(global.otherplayer);

if(size < 0)break;

if(size == 0)

{

show_message("Drugi gracz opuscil gre.");

instance_destroy();

break;

}

mid = readbyte();

switch(mid)

{

case 0:

objPlayer1.y = readshort();

break;

 

case 1:

objBall.x = readshort();

objBall.y = readshort();

break;

}

}

- Strzałka W Góre

GML
if(y > 0 and !global.host)

{

y -= 5;

event_user(0);

}

- Strzałka W Dół

GML
if(y + sprite_height < room_height and !global.host)

{

y += 5;

event_user(0);

}

- User Defined 0

GML
clearbuffer();

writebyte(0);

writeshort(y);

sendmessage(global.otherplayer);

Pamiętaj także, aby w evencie Game End dodać kod:

GML
dllfree()

Obiekt z tym eventem musi byc w kazdym pokoju, ten kod zwolni dll z pamieci naszego komputera :P

Download(GMK+EXE): https://gmclan.org/up5379_4_Pong.html

39DLL(Należy wkleić do folderu z grą): https://gmclan.org/up5379_4_39dll.html

 

Nie czepiać się tego że większość w poradniku to kod, bo to nie pokazuje wszystkich funkcji tego DLL, tylko te które są potrzebne.

Jeśli będą problemy, proszę pisać, a jeśli znajdziecie błąd u mnie, tutaj w kodzie to także pisać. Wiem, że to mało, no bo to taki mini kurs.

To już koniec, mam nadzieje że coś się nauczycie, o korzystaniu z 39DLL. Jest on znacznie szybszy, wygodniejszy i lepszy niż wbudowany mplay.

Pozdro

Roki

Odnośnik do komentarza
Udostępnij na innych stronach

No no solidna praca to genialna praca :)

W pliku .exe i w przykładzie po przycisku "run" otwiera się nie gra, lecz:

 

___________________________________________

ERROR in

action number 1

of Key Release Event for <unknown> Key

for object objHost:

 

Error defining an external function.

Odnośnik do komentarza
Udostępnij na innych stronach

Czy mi się wydaje, czy Ty wysyłasz jedynie x i y piłki, i to co stepa :o ?

Wysyłaj x, y, direction i ew. speed (jeśli się zmienia) z serwa do klienta tylko w momencie, kiedy direction/speed się zmienia (np. po odbiciu paletką piłki)... ;/

 

Metoda z eventem User Defined jest bez sensu - po kij rozbijać kod na 3 eventy, jak można mieć wszystko ładnie, w jednym evencie?

Odnośnik do komentarza
Udostępnij na innych stronach

hmm, ale na yoyogames wraz z przykladem online engine v2 (zabugowanym rzecz jasna) chyba byl przyklad pingponga przez siec. nie myle sie?

Odnośnik do komentarza
Udostępnij na innych stronach

Wysyłaj x, y, direction i ew. speed - Po *********

Lepiej samo x i y, a nie wszystko.

=|

 

Po 1. Kwestia wygody. Przy Twoim ######stym sposobie wysyłania pozycji CO STEPA, już przy pingu 100ms piłka będzie się ruszać 10 razy na sekundę - łoł, taka gra to prawdziwa przyjemność ^_^

Po 2. Kwestia wydajnościowa - nie wysyłaj czegoś CO STEPA, jeśli możesz coś wysłać RAZ - które wydaje Ci się lepsze...?

Nie dość, że wydajniej (optymalniej), to na dodatek lepiej, eh...

 

Kurde, jak Ty możesz kogoś chcieć uczyć, jak sam takich podstaw nie rozumiesz...? ;/

Zapamiętaj, że chodzi o to, żeby wysyłać jak NAJMNIEJ informacji.

I nigdy nic co Stepa :o

 

Zresztą, popytaj powiedzmy gnyska (Almora) na ten temat, bo mi się już pisać nie chce.

 

I nie kłóć się ;x

Odnośnik do komentarza
Udostępnij na innych stronach

  • Administratorzy

Potwierdzam. ja bym wysyłał x,y,direction co 10 stepów. Speed nie potrzebny, bo przecież sie nie zmienia i obu graczy jest ten sam. Piłka nie poleci za daleko, bo 3 razy na sekunde pozycja jest porpawiana przez x,y i właściwy direction.

Odnośnik do komentarza
Udostępnij na innych stronach

Hmm... Zakładając, że kąt odbicia = kąt padania możesz wysłać direction tylko na początku gry, a odbicia i tak będą takie same u obu graczy :)

 

Dokładnie, tak samo bym to zrobił, jedynie dodałbym, że co odbicie sprawdza pozycję i kierunek piłki żeby nie było różnicy pomiędzy dwoma graczami, bo jak wiadomo w necie różne rzeczy się dzieją :)

Odnośnik do komentarza
Udostępnij na innych stronach

Dawidds: Nie ma lag nawet jak co stepa wysyłam tongue2.gif Sprawdź sam, to dzięki funkcji setnagle tak się dzieje biggrin.gif
...

Już nie próbuj się bronić na siłę.

Wysyłasz kilkanaście/set bajtów więcej, niż byś mógł.

 

Nobody, zauważ, iż pozycje paletek u obu graczy mogą się mniej lub bardziej różnić w momencie odbicia.

 

Borek: Przecie dokładnie o tym mówiłem : o

Czytałeś temat :D ?

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...